package cn.mysdp.utils;

import cn.mysdp.biz.dto.response.SdpProjectQueryResponse;
import cn.mysdp.biz.dto.response.SdpTemplateQueryResponse;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import jdk.nashorn.api.scripting.ScriptObjectMirror;
import lombok.Getter;
import lombok.Setter;
import org.apache.tomcat.util.security.MD5Encoder;
import org.mybatis.generator.api.IntrospectedColumn;
import org.mybatis.generator.api.IntrospectedTable;
import org.mybatis.generator.api.dom.java.FullyQualifiedJavaType;
import org.mybatis.generator.internal.db.SqlReservedWords;
import org.mybatis.generator.internal.util.StringUtility;
import org.postgresql.util.MD5Digest;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.script.*;

import javax.sql.DataSource;
import java.io.File;
import java.lang.reflect.Method;
import java.security.MessageDigest;
import java.util.*;

import static org.mybatis.generator.internal.util.StringUtility.escapeStringForJava;

/**
 * @ClassName:
 * @Description:
 * @Author: SDP
 * @Date: 2020-10-30
 * Table:
 * Comment:
 */
@Getter
@Setter
public class ProcessUtil {

    ScriptEngineManager manager = new ScriptEngineManager();
    // 获取JavaScript引擎
    ScriptEngine engine = null;

    public Object js(String js) {
        return js(js, null);
    }
    public Object js(String js, Bindings n) {
        try {
            if(engine == null) {
                engine = manager.getEngineByName("nashorn");
            }
            Object obj;
            if(n != null) {
                obj = engine.eval(js, n);
            } else {
                obj = engine.eval(js);
            }
            if(obj instanceof ScriptObjectMirror) {
                ScriptObjectMirror so = (ScriptObjectMirror)obj;
                if(so.isArray()) {
                    Collection<Object> v = so.values();
                    List<Object> vs = new ArrayList<>();
                    vs.addAll(v);
                    return JSONArray.parseArray(JSONArray.toJSONString(vs, SerializerFeature.DisableCircularReferenceDetect));
                }
                String str = JSONObject.toJSONString(obj, SerializerFeature.DisableCircularReferenceDetect);
                return JSONObject.parseObject(str);
            }
            return obj;
        }catch (Exception ex) {
            ex.printStackTrace();
            throw new RuntimeException(ex);
        }

    }

    public DynProcessTokenResult processBodyToken(DataSource dataSource, IntrospectedTable introspectedTable, SdpTemplateQueryResponse dynTemplate, String fileName, String sqlMethodName, List<ByteWithPos> lineBytesList, List<String> lineStringList, List<String> lineTrimStringList, List<Integer> deepList, int deep, ByteWithPos destBytes, String vTrim, List<IntrospectedColumn> inColumns, Object _processInstance, Method _processBodyToken, Method _processToken) throws Exception {
        JSONObject properties = processStarProperties(vTrim);

        DynProcessTokenResult result;
        try {
            result = (DynProcessTokenResult) _processBodyToken.invoke(_processInstance, dataSource, introspectedTable, dynTemplate, fileName, sqlMethodName, lineBytesList, lineStringList, lineTrimStringList, deepList, deep, destBytes, vTrim, properties, inColumns);
        }catch(Exception ex) {
            ex.printStackTrace(System.err);
            throw ex;
        }
        if (result.getProcessed()) {
            return result;
        }
        result = new DynProcessTokenResult();

        List<IntrospectedColumn> introspectedColumns = null;
        Map<String, IntrospectedColumn> sqlParamNameMap = new HashMap<>();

        Set<String> doneSet = new HashSet<>();
        List<IntrospectedColumn> extraColumns = new ArrayList<>();

        {
            DynProcessTokenResult result1 = processBodyTokenProperties(dataSource, introspectedTable, dynTemplate, fileName, sqlMethodName, lineBytesList, lineStringList, lineTrimStringList, deepList, deep, destBytes, vTrim, properties, inColumns);
            if (result1.getProcessed()) {
                result.setProcessed(true);
                result.setResult(result1.getResult());
                return result;
            }
        }

        if (inColumns != null) {
            result.setProcessed(true);
            introspectedColumns = inColumns;
        }else if (isBlockToken(vTrim,"table")) {
            introspectedColumns = new ArrayList<>();
            IntrospectedColumn newColumn = new IntrospectedColumn();
            newColumn.setContext(introspectedTable.getContext());
            introspectedColumns.add(newColumn);
            newColumn.setActualColumnName(introspectedTable.getTableConfiguration().getTableName());
            newColumn.setFullyQualifiedJavaType(FullyQualifiedJavaType.getStringInstance());
            newColumn.setRemarks(introspectedTable.getRemarks());
            sqlMethodName = null;
        }else if (isBlockToken(vTrim,"tables")) {
            introspectedColumns = new ArrayList<>();
            String tablesStr = introspectedTable.getDynProject().getTables();
            if (!StringUtils.isEmpty(tablesStr)) {
                String[] tables = tablesStr.split(",");
                for(String name: tables) {
                    name = name.trim();
                    if (StringUtils.isEmpty(name)) {
                        continue;
                    }
                    String[] names = name.split(" as ");
                    String alias = names[0].trim();
                    if (names.length > 1) {
                        name = names[0].trim();
                        alias = names[1].trim();
                    }
                    IntrospectedColumn newColumn = new IntrospectedColumn();
                    newColumn.setContext(introspectedTable.getContext());
                    introspectedColumns.add(newColumn);
                    newColumn.setActualColumnName(alias);
                    newColumn.setFullyQualifiedJavaType(FullyQualifiedJavaType.getStringInstance());
                }
            }
            sqlMethodName = null;
        } else if (isBlockToken(vTrim,"sql")) {
            result.setProcessed(true);
            introspectedColumns = new ArrayList<>();
            if (!StringUtils.isEmpty(sqlMethodName)) {

                introspectedColumns = new ArrayList<>();
                for (String key : cn.mysdp.utils.JavaBeansUtil.getParameterColumnsKeys(introspectedTable)) {
                    List<IntrospectedColumn> columns = introspectedTable.getParameterColumns().get(key);
                    for(IntrospectedColumn column: columns) {
                        if ("sql".equals(column.getParameterCatalog()) && sqlMethodName.equals(column.getActualColumnName())) {
                            introspectedColumns.add(column);
                        }
                    }
                }

            }
        } else if (isBlockToken(vTrim,"columns")) {
            result.setProcessed(true);
            if ("1".equals(properties.getString("only_primary_key"))) {
                List<IntrospectedColumn> columns = introspectedTable.getPrimaryKeyColumns();
                if (columns == null || columns.size() == 0) {
                    introspectedColumns = new ArrayList<>();
                } else {
                    introspectedColumns = columns;
                }
            } else {
                if (StringUtils.hasText(sqlMethodName)) {
                    introspectedColumns = new ArrayList<>();
                    List<IntrospectedColumn> oriColumns = introspectedTable.getParameterColumns().get("api.request_for_sql."+sqlMethodName);
                    if (oriColumns == null) {
                        throw new Exception("逻辑错误："+fileName + ","+sqlMethodName);
                    }
                    List<IntrospectedColumn> columnsForSql = introspectedTable.getParameterColumns().get("api.all_columns_for_sql."+sqlMethodName);
                    if (columnsForSql == null) {
                        throw new Exception("逻辑错误："+fileName + ","+sqlMethodName);
                    }
                    Map<String, IntrospectedColumn> oriColumnMap = new HashMap<>();
                    for(IntrospectedColumn column1: oriColumns) {
                        oriColumnMap.put(column1.getActualColumnName(), column1);
                    }
                    if (oriColumns != null) {
                        introspectedColumns.addAll(oriColumns);
                    }
                    if ("1".equals(properties.getString("is_only_param_columns")) || "1".equals(properties.getString("is_only_request_columns"))) {
                        introspectedColumns = new ArrayList<>();
                        List<IntrospectedColumn> extraColumns2 = introspectedTable.getParameterColumns().get("sql.param."+sqlMethodName);
                        if (extraColumns2 != null) {
                            extraColumns.addAll(extraColumns2);
                        }
                    } else if ("1".equals(properties.getString("is_only_response_columns"))) {
                        introspectedColumns = new ArrayList<>();
                        List<IntrospectedColumn> extraColumns2 = introspectedTable.getParameterColumns().get("sql.response." + sqlMethodName);
                        if (extraColumns2 != null) {
                            extraColumns.addAll(extraColumns2);
                        }
                    } else if ("1".equals(properties.getString("is_only_miss_extra_request_columns"))) {
                        introspectedColumns = new ArrayList<>();
                        List<IntrospectedColumn> extraColumns2 = introspectedTable.getParameterColumns().get("sql.param." + sqlMethodName);
                        if (extraColumns2 != null) {
                            for(IntrospectedColumn column: extraColumns2) {
                                if(!oriColumnMap.containsKey(column.getActualColumnName())) {
                                    extraColumns.add(column);
                                }
                            }
                        }
                    } else if ("1".equals(properties.getString("is_only_miss_extra_response_columns"))) {
                        introspectedColumns = new ArrayList<>();
                        List<IntrospectedColumn> extraColumns2 = introspectedTable.getParameterColumns().get("sql.response." + sqlMethodName);
                        if (extraColumns2 != null) {
                            for(IntrospectedColumn column: extraColumns2) {
                                if(!oriColumnMap.containsKey(column.getActualColumnName())) {
                                    extraColumns.add(column);
                                }
                            }
                        }
                    }else {
                        if ("1".equals(properties.getString("include_param_columns")) || "1".equals(properties.getString("include_request_columns"))) {
                            List<IntrospectedColumn> extraColumns2 = introspectedTable.getParameterColumns().get("sql.param." + sqlMethodName);
                            if(extraColumns2 != null) {
                                extraColumns.addAll(extraColumns2);
                            }
                        }

                    }

                    {
                        String name = null;
                        if("1".equals(properties.getString("is_both_request_columns"))) {
                            name = sqlMethodName;
                        }
                        List<IntrospectedColumn> extraColumns2 = null;
                        if(name != null) {
                            if (introspectedTable.getParameterColumns() != null && introspectedTable.getParameterColumns().containsKey("sql.param." + name)) {
                                extraColumns2 = introspectedTable.getParameterColumns().get("sql.param." + name);
                            }
                            if(extraColumns2 != null) {
                                List<IntrospectedColumn> columns2 = new ArrayList<>();
                                Map<String, IntrospectedColumn> extraColumns2Map = new HashMap<>();
                                for(IntrospectedColumn column: extraColumns2) {
                                    extraColumns2Map.put(column.getActualColumnName(), column);
                                }
                                for(IntrospectedColumn column: introspectedColumns) {
                                    if(extraColumns2Map.containsKey(column.getActualColumnName())) {
                                        columns2.add(extraColumns2Map.get(column.getActualColumnName()));
                                    }
                                }
                                introspectedColumns = columns2;
                            } else {
                                introspectedColumns = new ArrayList<>();
                            }
                        }
                    }

                    {
                        String name = null;
                        if("1".equals(properties.getString("is_both_response_columns"))) {
                            name = sqlMethodName;
                        }
                        List<IntrospectedColumn> extraColumns2 = null;
                        if(name != null) {
                            if (introspectedTable.getParameterColumns() != null && introspectedTable.getParameterColumns().containsKey("sql.response." + name)) {
                                extraColumns2 = introspectedTable.getParameterColumns().get("sql.response." + name);
                            }
                            if(extraColumns2 != null) {
                                List<IntrospectedColumn> columns2 = new ArrayList<>();
                                Map<String, IntrospectedColumn> extraColumns2Map = new HashMap<>();
                                for(IntrospectedColumn column: extraColumns2) {
                                    extraColumns2Map.put(column.getActualColumnName(), column);
                                }
                                for(IntrospectedColumn column: introspectedColumns) {
                                    if(extraColumns2Map.containsKey(column.getActualColumnName())) {
                                        columns2.add(extraColumns2Map.get(column.getActualColumnName()));
                                    }
                                }
                                introspectedColumns = columns2;
                            } else {
                                introspectedColumns = new ArrayList<>();
                            }
                        }
                    }

                    {
                        String name = null;
                        if("1".equals(properties.getString("is_no_extra_request_columns"))) {
                            name = sqlMethodName;
                        }
                        List<IntrospectedColumn> extraColumns2 = null;
                        if(name != null) {
                            if (introspectedTable.getParameterColumns() != null && introspectedTable.getParameterColumns().containsKey("sql.param." + name)) {
                                extraColumns2 = introspectedTable.getParameterColumns().get("sql.param." + name);
                            }
                            if(extraColumns2 != null) {
                                List<IntrospectedColumn> columns2 = new ArrayList<>();
                                Set<String> extraColumns2Set = new HashSet<>();
                                for(IntrospectedColumn column: extraColumns2) {
                                    extraColumns2Set.add(column.getActualColumnName());
                                }
                                for(IntrospectedColumn column: introspectedColumns) {
                                    if(!extraColumns2Set.contains(column.getActualColumnName())) {
                                        columns2.add(column);
                                    }
                                }
                                introspectedColumns = columns2;
                            }
                        }
                        extraColumns2 = null;
                        name = null;
                        if("1".equals(properties.getString("is_no_extra_response_columns"))) {
                            name = sqlMethodName;
                        }
                        if(name != null) {
                            if (introspectedTable.getParameterColumns() != null && introspectedTable.getParameterColumns().containsKey("sql.response." + name)) {
                                extraColumns2 = introspectedTable.getParameterColumns().get("sql.response." + name);
                            }
                            if(extraColumns2 != null) {
                                List<IntrospectedColumn> columns2 = new ArrayList<>();
                                Set<String> extraColumns2Set = new HashSet<>();
                                for(IntrospectedColumn column: extraColumns2) {
                                    extraColumns2Set.add(column.getActualColumnName());
                                }
                                for(IntrospectedColumn column: introspectedColumns) {
                                    if(!extraColumns2Set.contains(column.getActualColumnName())) {
                                        columns2.add(column);
                                    }
                                }
                                introspectedColumns = columns2;
                            }
                        }
                    }

                    if ("1".equals(properties.getString("include_response_columns"))
                            || "1".equals(properties.getString("is_only_response_columns"))
                    ) {
                        List<IntrospectedColumn> extraColumns2 = introspectedTable.getParameterColumns().get("sql.response." + sqlMethodName);
                        if(extraColumns2 != null) {
                            extraColumns.addAll(extraColumns2);
                        }
                    }
                    if ("1".equals(properties.getString("include_param_columns"))
                            || "1".equals(properties.getString("include_request_columns"))
                            || "1".equals(properties.getString("is_only_request_columns"))
                            || "1".equals(properties.getString("is_only_param_columns"))
                    ) {
                        List<IntrospectedColumn> extraColumns2 = introspectedTable.getParameterColumns().get("sql.param." + sqlMethodName);
                        if(extraColumns2 != null) {
                            extraColumns.addAll(extraColumns2);
                        }
                    }
                } else {
                    Map<String, IntrospectedColumn> oriColumnMap = new HashMap<>();
                    if(!CollectionUtils.isEmpty(introspectedTable.getAllColumns())) {
                        for(IntrospectedColumn column1: introspectedTable.getAllColumns()) {
                            oriColumnMap.put(column1.getActualColumnName(), column1);
                        }
                    }

                    if ("1".equals(properties.getString("is_only_param_columns")) || "1".equals(properties.getString("is_only_request_columns"))) {
                        introspectedColumns = new ArrayList<>();
                    } else if(properties.containsKey("is_only_request_columns") || properties.containsKey("is_only_param_columns")) {
                        String name = properties.getString("is_only_request_columns");
                        if (!StringUtils.hasText(name)) {
                            name = properties.getString("is_only_param_columns");
                        }
                        introspectedColumns = new ArrayList<>();
                        if (introspectedTable.getParameterColumns() != null && introspectedTable.getParameterColumns().containsKey("api.request." + name)) {
                            List<IntrospectedColumn> extraColumns2 = introspectedTable.getParameterColumns().get("api.request." + name);
                            extraColumns.addAll(extraColumns2);
                        }
                    } else if ("1".equals(properties.getString("is_only_response_columns"))) {
                        introspectedColumns = new ArrayList<>();
                    } else if(properties.containsKey("is_only_response_columns")) {
                        String name = properties.getString("is_only_response_columns");
                        introspectedColumns = new ArrayList<>();
                        if (introspectedTable.getParameterColumns() != null && introspectedTable.getParameterColumns().containsKey("api.response." + name)) {
                            List<IntrospectedColumn> extraColumns2 = introspectedTable.getParameterColumns().get("api.response." + name);
                            extraColumns.addAll(extraColumns2);
                        }
                    } else if(properties.containsKey("is_only_miss_extra_request_columns")) {
                        introspectedColumns = new ArrayList<>();
                        String names[] = new String[0];
                        if("1".equals(properties.getString("is_only_miss_extra_request_columns"))) {
                            names = "list".split(",");
                        } else {
                            names = properties.getString("is_only_miss_extra_request_columns").split(",");
                        }
                        Set<String> doneSet2 = new HashSet<>();
                        for(String name: names) {
                            name = name.trim();
                            if(StringUtils.hasText(name)) {
                                if (introspectedTable.getParameterColumns() != null && introspectedTable.getParameterColumns().containsKey("api.request." + name)) {
                                    List<IntrospectedColumn> extraColumns2 = introspectedTable.getParameterColumns().get("api.request." + name);
                                    if(extraColumns2 != null) {
                                        for(IntrospectedColumn column: extraColumns2) {
                                            if(!oriColumnMap.containsKey(column.getActualColumnName()) && !doneSet2.contains(column.getActualColumnName())) {
                                                doneSet2.add(column.getActualColumnName());
                                                extraColumns.add(column);
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    } else if(properties.containsKey("is_only_miss_extra_response_columns")) {
                        introspectedColumns = new ArrayList<>();
                        String names[] = new String[0];
                        if("1".equals(properties.getString("is_only_miss_extra_response_columns"))) {
                            names = "list".split(",");
                        } else {
                            names = properties.getString("is_only_miss_extra_response_columns").split(",");
                        }
                        Set<String> doneSet2 = new HashSet<>();
                        for(String name: names) {
                            name = name.trim();
                            if (StringUtils.hasText(name)) {
                                if (introspectedTable.getParameterColumns() != null && introspectedTable.getParameterColumns().containsKey("api.response." + name)) {
                                    List<IntrospectedColumn> extraColumns2 = introspectedTable.getParameterColumns().get("api.response." + name);
                                    if(extraColumns2 != null) {
                                        for(IntrospectedColumn column: extraColumns2) {
                                            if(!oriColumnMap.containsKey(column.getActualColumnName()) && !doneSet2.contains(column.getActualColumnName())) {
                                                doneSet2.add(column.getActualColumnName());
                                                extraColumns.add(column);
                                            }
                                        }
                                    }
                                }
                            }
                        }

                    } else {
                        introspectedColumns = introspectedTable.getAllColumns();
                    }

                    {
                        String[] names = new String[0];
                        if("1".equals(properties.getString("is_both_request_columns"))) {
                            names = "list".split(",");
                        } else if(properties.containsKey("is_both_request_columns")) {
                            names = properties.getString("is_both_request_columns").split(",");
                        }

                        List<IntrospectedColumn> extraColumns2 = null;
                        Map<String, IntrospectedColumn> extraColumns2Map = new HashMap<>();
                        Set<String> doneSet2 = new HashSet<>();
                        for(String name: names) {
                            name = name.trim();
                            if(StringUtils.hasText(name)) {
                                if (introspectedTable.getParameterColumns() != null && introspectedTable.getParameterColumns().containsKey("api.request." + name)) {
                                    extraColumns2 = introspectedTable.getParameterColumns().get("api.request." + name);
                                }
                                if(extraColumns2 != null) {
                                    List<IntrospectedColumn> columns2 = new ArrayList<>();
                                    for(IntrospectedColumn column: extraColumns2) {
                                        extraColumns2Map.put(column.getActualColumnName(), column);
                                    }
                                    for(IntrospectedColumn column: introspectedColumns) {
                                        if(extraColumns2Map.containsKey(column.getActualColumnName()) && !doneSet2.contains(column.getActualColumnName())) {
                                            doneSet2.add(column.getActualColumnName());
                                            columns2.add(extraColumns2Map.get(column.getActualColumnName()));
                                        }
                                    }
                                    introspectedColumns = columns2;
                                } else {
                                    introspectedColumns = new ArrayList<>();
                                }
                            }
                        }
                    }

                    {
                        String[] names = new String[0];
                        if("1".equals(properties.getString("is_both_response_columns"))) {
                            names = "list".split(",");
                        } else if(properties.containsKey("is_both_response_columns")) {
                            names = properties.getString("is_both_response_columns").split(",");
                        }

                        List<IntrospectedColumn> extraColumns2 = null;
                        Map<String, IntrospectedColumn> extraColumns2Map = new HashMap<>();
                        Set<String> doneSet2 = new HashSet<>();
                        for(String name: names) {
                            name = name.trim();
                            if(StringUtils.hasText(name)) {
                                if (introspectedTable.getParameterColumns() != null && introspectedTable.getParameterColumns().containsKey("api.response." + name)) {
                                    extraColumns2 = introspectedTable.getParameterColumns().get("api.response." + name);
                                }
                                if(extraColumns2 != null) {
                                    List<IntrospectedColumn> columns2 = new ArrayList<>();
                                    for(IntrospectedColumn column: extraColumns2) {
                                        extraColumns2Map.put(column.getActualColumnName(), column);
                                    }
                                    for(IntrospectedColumn column: introspectedColumns) {
                                        if(extraColumns2Map.containsKey(column.getActualColumnName()) && !doneSet2.contains(column.getActualColumnName())) {
                                            doneSet2.add(column.getActualColumnName());
                                            columns2.add(extraColumns2Map.get(column.getActualColumnName()));
                                        }
                                    }
                                    introspectedColumns = columns2;
                                } else {
                                    introspectedColumns = new ArrayList<>();
                                }
                            }
                        }
                    }

                    {
                        List<IntrospectedColumn> extraColumns2 = null;
                        Set<String> extraColumns2Set = new HashSet<>();
                        String[] names = new String[0];
                        if ("1".equals(properties.getString("is_no_extra_request_columns"))) {
                            names = "list".split(",");
                        } else if (properties.containsKey("is_no_extra_request_columns")) {
                            names = properties.getString("is_no_extra_request_columns").split(",");
                        }
                        for (String name : names) {
                            name = name.trim();
                            if (StringUtils.hasText(name)) {
                                if (introspectedTable.getParameterColumns() != null && introspectedTable.getParameterColumns().containsKey("api.request." + name)) {
                                    extraColumns2 = introspectedTable.getParameterColumns().get("api.request." + name);
                                }
                                if (extraColumns2 != null) {
                                    List<IntrospectedColumn> columns2 = new ArrayList<>();
                                    for (IntrospectedColumn column : extraColumns2) {
                                        extraColumns2Set.add(column.getActualColumnName());
                                    }
                                    for (IntrospectedColumn column : introspectedColumns) {
                                        if (!extraColumns2Set.contains(column.getActualColumnName())) {
                                            columns2.add(column);
                                        }
                                    }
                                    introspectedColumns = columns2;
                                }
                            }
                        }
                        extraColumns2 = null;
                    }
                    {
                        List<IntrospectedColumn> extraColumns2 = null;
                        String[] names = new String[0];
                        if("1".equals(properties.getString("is_no_extra_response_columns"))) {
                            names = "list".split(",");
                        } else if(properties.containsKey("is_no_extra_response_columns")) {
                            names = properties.getString("is_no_extra_response_columns").split(",");
                        }
                        Set<String> extraColumns2Set = new HashSet<>();
                        for(String name: names) {
                            name = name.trim();
                            if (StringUtils.hasText(name)) {
                                if (introspectedTable.getParameterColumns() != null && introspectedTable.getParameterColumns().containsKey("api.response." + name)) {
                                    extraColumns2 = introspectedTable.getParameterColumns().get("api.response." + name);
                                }
                                if(extraColumns2 != null) {
                                    List<IntrospectedColumn> columns2 = new ArrayList<>();
                                    for(IntrospectedColumn column: extraColumns2) {
                                        extraColumns2Set.add(column.getActualColumnName());
                                    }
                                    for(IntrospectedColumn column: introspectedColumns) {
                                        if(!extraColumns2Set.contains(column.getActualColumnName())) {
                                            columns2.add(column);
                                        }
                                    }
                                    introspectedColumns = columns2;
                                }
                            }
                        }
                    }

                    if ("1".equals(properties.getString("is_replace_by_sql"))) {
                        List<IntrospectedColumn> _replaceCols = cn.mysdp.utils.JavaBeansUtil.getReplaceTableRequestIntrospectedColumn(introspectedTable);
                        if(_replaceCols != null){
                            introspectedColumns = _replaceCols;
                        }
                    }
                    if (properties.containsKey("extra_request_columns")) {
                        String[] names = new String[0];
                        if ("1".equals(properties.getString("extra_request_columns"))) {
                            names = "list".split(",");
                        } else if (properties.containsKey("extra_request_columns")) {
                            names = properties.getString("extra_request_columns").split(",");
                        }
                        Set<String> doneSet2 = new HashSet<>();
                        for (String name : names) {
                            name = name.trim();
                            if (StringUtils.hasText(name)) {
                                if (introspectedTable.getParameterColumns() != null && introspectedTable.getParameterColumns().containsKey("api.request." + name)) {
                                    List<IntrospectedColumn> extraColumns2 = introspectedTable.getParameterColumns().get("api.request." + name);
                                    if(extraColumns2 != null) {
                                        for(IntrospectedColumn column: extraColumns2) {
                                            if(!doneSet2.contains(column.getActualColumnName())) {
                                                doneSet2.add(column.getActualColumnName());
                                                extraColumns.add(column);
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                    if (properties.containsKey("extra_response_columns")) {
                        String[] names = new String[0];
                        if ("1".equals(properties.getString("extra_response_columns"))) {
                            names = "list".split(",");
                        } else if (properties.containsKey("extra_response_columns")) {
                            names = properties.getString("extra_response_columns").split(",");
                        }
                        Set<String> doneSet2 = new HashSet<>();
                        for (String name : names) {
                            name = name.trim();
                            if (StringUtils.hasText(name)) {
                                if (introspectedTable.getParameterColumns() != null && introspectedTable.getParameterColumns().containsKey("api.response." + name)) {
                                    List<IntrospectedColumn> extraColumns2 = introspectedTable.getParameterColumns().get("api.response." + name);
                                    if(extraColumns2 != null) {
                                        for(IntrospectedColumn column: extraColumns2) {
                                            if(!doneSet2.contains(column.getActualColumnName())) {
                                                doneSet2.add(column.getActualColumnName());
                                                extraColumns.add(column);
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }

                if("1".equals(properties.getString("include_all_sql_param"))) {
                    for(String _k: introspectedTable.getParameterColumnKeys()) {
                        if(_k.startsWith("sql.")) {
                            for(IntrospectedColumn _c: introspectedTable.getParameterColumns().get(_k)) {
                                extraColumns.add(_c);
                            }
                        }
                    }
                }

                if(!CollectionUtils.isEmpty(extraColumns)) {
                    List<IntrospectedColumn> extraColumns2 = extraColumns;
                    if (extraColumns2 != null) {
                        Map<String, IntrospectedColumn> _extraColumnsMap = new HashMap<>();
                        Set<String> _doneSet = new HashSet<>();
                        for(IntrospectedColumn _c : extraColumns2) {
                            _extraColumnsMap.put(_c.getActualColumnName(), _c);
                        }
                        if(!CollectionUtils.isEmpty(_extraColumnsMap)) {
                            List<IntrospectedColumn> _newColumns = new ArrayList<>();

                            for(IntrospectedColumn _c : introspectedColumns) {
                                IntrospectedColumn _extraColumn = _extraColumnsMap.get(_c.getActualColumnName());
                                if(_extraColumn == null) {
                                    _newColumns.add(_c);
                                } else {
                                    _newColumns.add(_extraColumn);
                                    if(!StringUtils.hasText(_extraColumn.getRemarks())) {
                                        _extraColumn.setRemarks(_c.getRemarks());
                                    }
                                }
                                _doneSet.add(_c.getActualColumnName());
                            }
                            for(IntrospectedColumn _c : extraColumns2) {
                                if(!doneSet.contains(_c.getActualColumnName())) {
                                    _newColumns.add(_c);
                                    _doneSet.add(_c.getActualColumnName());
                                }
                            }
                            introspectedColumns = _newColumns;
                        }
                    }
                }
            }
        } else if (isBlockToken(vTrim,"sqls")) {
            introspectedColumns = new ArrayList<>();
            for (String key : cn.mysdp.utils.JavaBeansUtil.getParameterColumnsKeys(introspectedTable)) {
                List<IntrospectedColumn> columns = introspectedTable.getParameterColumns().get(key);
                for(IntrospectedColumn column: columns) {
                    if ("sql".equals(column.getParameterCatalog())) {
                        introspectedColumns.add(column);
                    }
                }
            }
        } else if (isBlockToken(vTrim,"methods")) {
            result.setProcessed(true);
            introspectedColumns = new ArrayList<>();
            for (String key : introspectedTable.getParameterColumnKeys()) {
                List<IntrospectedColumn> columns = introspectedTable.getParameterColumns().get(key);
                if (!CollectionUtils.isEmpty(columns)) {
                    IntrospectedColumn column = columns.get(0);
                    if ("api.facade".equals(column.getParameterCatalog())) {
                        introspectedColumns.add(column);
                    }
                }
            }
        } else {
            ByteWithPos.appendDestBytes(destBytes, vTrim + System.lineSeparator());
        }
        if (!CollectionUtils.isEmpty(extraColumns)) {
            for(IntrospectedColumn column: extraColumns) {
                sqlParamNameMap.put(column.getActualColumnName(), column);
            }
        }

        processBodyTokenWithColumns(dataSource, introspectedTable, dynTemplate, fileName, sqlMethodName, lineBytesList, lineStringList, lineTrimStringList, deepList, deep, destBytes, vTrim, properties, inColumns, introspectedColumns, extraColumns, _processInstance, _processBodyToken, _processToken);
        return result;
    }

    public void processBodyTokenWithColumns(DataSource dataSource, IntrospectedTable introspectedTable, SdpTemplateQueryResponse dynTemplate, String fileName, String sqlMethodName, List<ByteWithPos> lineBytesList, List<String> lineStringList, List<String> lineTrimStringList, List<Integer> deepList, int deep, ByteWithPos destBytes, String vTrim, JSONObject properties, List<IntrospectedColumn> inColumns, List<IntrospectedColumn> introspectedColumns, List<IntrospectedColumn> extraColumns, Object _processInstance, Method _processBodyToken, Method _processToken) throws Exception {
        Map<String, IntrospectedColumn> sqlParamNameMap = new HashMap<>();
        if (!CollectionUtils.isEmpty(extraColumns)) {
            for(IntrospectedColumn column: extraColumns) {
                sqlParamNameMap.put(column.getActualColumnName(), column);
            }
        }

        if (CollectionUtils.isEmpty(introspectedColumns) && !"1".equals(properties.getString("empty_as_table")+"")) {
            if(properties.containsKey("content_id")) {
                introspectedTable.getDynWorkspace().getExtraMap().put(properties.getString("content_id"), "");
            }
            return;
        }
        if(!"0".equals("is_fix_dup")) {
            introspectedColumns = fixIntrospectedColumns(introspectedTable, dynTemplate, introspectedColumns, properties, sqlParamNameMap, fileName, sqlMethodName);
        }

        if (CollectionUtils.isEmpty(introspectedColumns)) {
            if ("1".equals(properties.getString("empty_as_table")+"")) {
                System.out.println("empty_as_table:"+introspectedTable.getTableConfiguration().getTableName());
                introspectedColumns = new ArrayList<>();
                IntrospectedColumn newColumn = new IntrospectedColumn();
                newColumn.setContext(introspectedTable.getContext());
                introspectedColumns.add(newColumn);
                newColumn.setActualColumnName(introspectedTable.getTableConfiguration().getTableName());
                newColumn.setFullyQualifiedJavaType(FullyQualifiedJavaType.getStringInstance());
                newColumn.setRemarks(introspectedTable.getRemarks());
            }
        } else {
            if ("1".equals(properties.getString("not_empty_as_empty")+"")) {
                introspectedColumns.clear();
            }
        }
        if (CollectionUtils.isEmpty(introspectedColumns)) {
            if(properties.containsKey("content_id")) {
                introspectedTable.getDynWorkspace().getExtraMap().put(properties.getString("content_id"), "");
            }
            return;
        }

        Set<String> doneSet = new HashSet<>();

        int columnIndex = 0;
        ByteWithPos content = new ByteWithPos(1024);
        for(IntrospectedColumn column: introspectedColumns) {
            columnIndex++;
            ByteWithPos bodyBytes = new ByteWithPos(1024);

            boolean hasContent = false;
            for(int i = 0; i < deepList.size(); i++) {
                if (deepList.get(i) < deep) {
                    continue;
                }
                if (deepList.get(i) == deep) {
                    if (lineTrimStringList.get(i).startsWith("{*")) {
                        continue;
                    }
                    if (lineBytesList.get(i).pos == 0) {
                        ByteWithPos.appendLineSeperator(bodyBytes);
                        continue;
                    }
                    ByteWithPos tempBytes = new ByteWithPos(1024);
                    if ("".equals(lineTrimStringList.get(i))) {
                        if (hasContent) {
                            ByteWithPos.appendDestBytes(bodyBytes, lineStringList.get(i));
                            ByteWithPos.appendLineSeperator(bodyBytes);
                        }
                        continue;
                    }
                    processLine(dataSource, introspectedTable, dynTemplate, fileName, sqlMethodName, lineBytesList.get(i), tempBytes, introspectedColumns, columnIndex, _processInstance, _processBodyToken, _processToken);
                    if (tempBytes.pos > 0) {
                        hasContent = true;
                        ByteWithPos.appendDestBytes(bodyBytes, tempBytes.bytes, 0, tempBytes.pos);
                    } else {
                        hasContent = false;
                    }
                }
                if (deepList.get(i) > deep) {
                    String subVTrim = lineTrimStringList.get(i);
                    List<ByteWithPos> subLineBytesList = new ArrayList<>();
                    List<String> subLineStringList = new ArrayList<>();
                    List<String> subLineTrimStringList = new ArrayList<>();
                    List<Integer> subDeepList = new ArrayList<>();

                    int subDeep = deepList.get(i);
                    while(i < deepList.size() && deepList.get(i) > deep) {
                        subLineBytesList.add(lineBytesList.get(i));
                        subLineStringList.add(lineStringList.get(i));
                        subLineTrimStringList.add(lineTrimStringList.get(i));
                        subDeepList.add(deepList.get(i));
                        i++;
                    }
                    ByteWithPos subDestBytes = new ByteWithPos(1024);
                    List<IntrospectedColumn> subColumns = null;

                    if (isBlockToken(subVTrim,"unique_key_fields") && isBlockToken(vTrim, "unique_keys")) {
                        subColumns = introspectedTable.getUniqueColumns(column.getActualColumnName());
                    } else if (isBlockToken(subVTrim, "column")) {
                        subColumns = new ArrayList<>();
                        subColumns.add(column);
                    }

                    if (isBlockToken(vTrim, "sqls")) {
                        processBodyToken(dataSource, introspectedTable, dynTemplate, fileName, column.getParameterCatalogType(), subLineBytesList, subLineStringList, subLineTrimStringList, subDeepList, subDeep, subDestBytes, subVTrim, subColumns, _processInstance, _processBodyToken, _processToken);
                    } else if (!StringUtils.isEmpty(sqlMethodName)){
                        processBodyToken(dataSource, introspectedTable, dynTemplate, fileName, sqlMethodName, subLineBytesList, subLineStringList, subLineTrimStringList, subDeepList, subDeep, subDestBytes, subVTrim, subColumns, _processInstance, _processBodyToken, _processToken);
                    } else {
                        processBodyToken(dataSource, introspectedTable, dynTemplate, fileName, null, subLineBytesList, subLineStringList, subLineTrimStringList, subDeepList, subDeep, subDestBytes, subVTrim, subColumns, _processInstance, _processBodyToken, _processToken);
                    }
                    ByteWithPos.appendDestBytes(bodyBytes, subDestBytes.bytes, 0, subDestBytes.pos);
                    i--;
                    continue;
                }
            }
            String v = new String(bodyBytes.bytes, 0, bodyBytes.pos, "UTF-8");
            if (doneSet.contains(v)) {
                continue;
            }
            doneSet.add(v);
            ByteWithPos.appendDestBytes(destBytes, bodyBytes.bytes, 0, bodyBytes.pos);
            ByteWithPos.appendDestBytes(content, bodyBytes.bytes, 0, bodyBytes.pos);
        }

        if(properties.containsKey("content_id")) {
            String str = content.toString();
            introspectedTable.getDynWorkspace().getExtraMap().put(properties.getString("content_id"), str);
        }
    }

    public boolean isBlockToken(String tokenIn, String v) {
        tokenIn = tokenIn.trim();
        if (!tokenIn.startsWith("{*")) {
            return false;
        }
        tokenIn = tokenIn.substring(2);
        tokenIn = SplitUtil.split(tokenIn, "&")[0];
        tokenIn = SplitUtil.split(tokenIn, "}")[0];

//        return isTokenMD5(tokenIn, v);
        return tokenIn.equals(v);
    }

    public void processLine(DataSource dataSource, IntrospectedTable introspectedTable, SdpTemplateQueryResponse dynTemplate, String fileName, String sqlMethodName, ByteWithPos bodyBytes, ByteWithPos destBytes, List<IntrospectedColumn> columns, int columnIndex, Object _processInstance, Method _processBodyToken, Method _processToken) throws Exception {
        byte[] srcBytes = bodyBytes.bytes;
        int srcLength = bodyBytes.pos;

        ByteWithPos prefixBytes = new ByteWithPos(1024);
        ByteWithPos lineBytes = new ByteWithPos(1024);

        DynProcessTokenResult firstResult = null;
        DynProcessTokenResult lastResult = null;
        boolean ignoreLine = false;

        for(int pos = 0; pos < srcLength; pos++) {
            int srcPos = pos;
            while ( pos < srcLength && srcBytes[pos] != '{') {
                ByteWithPos.appendDestBytes(prefixBytes, srcBytes, pos, pos+1);
                pos++;
            }
            if (pos == srcLength) {
                if (prefixBytes.pos > 0) {
                    ByteWithPos.appendDestBytes(lineBytes, prefixBytes.bytes, 0, prefixBytes.pos);
                    prefixBytes = new ByteWithPos(1024);
                }
                break;
            }

            srcPos = pos++;
            ByteWithPos tokenBytes = new ByteWithPos(1024);
            while(pos < bodyBytes.pos) {
                if (srcBytes[pos] == '{') {
                    break;
                }
                if (srcBytes[pos] == '}') {
                    ByteWithPos.appendDestBytes(tokenBytes, srcBytes, srcPos, pos + 1);
                    break;
                }
                pos++;
            }
            if (tokenBytes.pos == 0) {
                if (prefixBytes.pos > 0) {
                    ByteWithPos.appendDestBytes(lineBytes, prefixBytes.bytes, 0, prefixBytes.pos);
                    prefixBytes = new ByteWithPos(1024);
                }
                ByteWithPos.appendDestBytes(lineBytes, srcBytes, srcPos, pos);
                pos--;
                continue;
            }

            String token = new String(tokenBytes.bytes, 0, tokenBytes.pos, "UTF-8");
            JSONObject properties = processStarProperties(token);

            String v = null;
            do {
                if (token.startsWith("{*")) {
                    lineBytes = new ByteWithPos(1024);
                    ByteWithPos.appendDestBytes(lineBytes, " ");
                    prefixBytes = new ByteWithPos(1024);
                    pos = srcLength;
                    break;
                }
                DynProcessTokenResult result = (DynProcessTokenResult) _processToken.invoke(_processInstance, dataSource, introspectedTable, dynTemplate, fileName, sqlMethodName, columns, columnIndex, token, properties);
                if (result.getProcessed()) {
                    v = result.getResult();
                    if(firstResult == null) {
                        firstResult = result;
                    }
                    lastResult = result;
                    break;
                }

                result = processToken(dataSource, introspectedTable, dynTemplate, fileName, sqlMethodName, columns, columnIndex, token, properties, _processInstance, _processBodyToken, _processToken, prefixBytes);
                if(result.getClearLine()) {
                    ignoreLine = true;
                }
                if (result.getProcessed()) {
                    v = result.getResult();
                    if(firstResult == null) {
                        firstResult = result;
                    }
                    lastResult = result;
                    break;
                }
                v = new String(srcBytes, srcPos, pos - srcPos + 1, "UTF-8");
            }while(false);

            if (v != null) {
                if (prefixBytes.pos > 0) {
                    ByteWithPos.appendDestBytes(lineBytes, prefixBytes.bytes, 0, prefixBytes.pos);
                    prefixBytes = new ByteWithPos(1024);
                }
                ByteWithPos.appendDestBytes(lineBytes, v);
            }
        }
        if (prefixBytes.pos > 0) {
            ByteWithPos.appendDestBytes(lineBytes, prefixBytes.bytes, 0, prefixBytes.pos);
            prefixBytes = new ByteWithPos(1024);
        }

        if(ignoreLine) {

        } else if (lineBytes.pos == 0) {
            if(firstResult != null && firstResult == lastResult && firstResult.getIgnoreBlock()) {
            } else {
                ByteWithPos.appendLineSeperator(destBytes);
            }
        } else {
            String v = new String(lineBytes.bytes, 0, lineBytes.pos, "UTF-8");
            if (!"".equals(v.trim())) {
                ByteWithPos.appendDestBytes(destBytes, lineBytes.bytes, 0, lineBytes.pos);
                ByteWithPos.appendDestBytes(destBytes, System.lineSeparator());
            }
        }
    }

    public DynProcessTokenResult processToken(DataSource dataSource, IntrospectedTable introspectedTable, SdpTemplateQueryResponse dynTemplate, String fileName, String sqlMethodName, List<IntrospectedColumn> columns, Integer columnIndex, String token, JSONObject properties, Object _processInstance, Method _processBodyToken, Method _processToken, ByteWithPos prefixBytes) throws Exception {
        DynProcessTokenResult result = new DynProcessTokenResult();
        String v = null;

        IntrospectedColumn column = null;
        if (columns != null && columnIndex > 0 && columnIndex <= columns.size()) {
            column = columns.get(columnIndex - 1);
        }

        JSONObject propertiesIsAjax = new JSONObject();
        propertiesIsAjax.put("is_ajax", "1");

        do {
            DynProcessTokenResult result1 = processTokenProperties(introspectedTable, dynTemplate, fileName, sqlMethodName, columns, columnIndex, token, properties);
            if (result1.getProcessed()) {
                result.setProcessed(true);
                result.setResult(result1.getResult());
                continue;
            }

            if (isToken(token, "alias_table_name")) {
                result.setProcessed(true);
                v = getName(token, dynTemplate.getAliasTableName(), properties, column, introspectedTable, dynTemplate);
            } else if (isToken(token, "table_name")) {
                result.setProcessed(true);
                v = getName(token, introspectedTable.getTableConfiguration().getTableName(), properties, column, introspectedTable, dynTemplate);
            } else if (isToken(token, "sql_name")) {
                result.setProcessed(true);
                if (StringUtils.isEmpty(sqlMethodName)) {
                    v = token + "<miss sql name>" + token;
                    continue;
                }
                do {
                    if("1".equals(properties.getString("is_page"))) {
                        IntrospectedColumn c = introspectedTable.getParameterColumns().get("sql."+sqlMethodName).get(0);
                        if (c != null) {
                            if(!StringUtils.hasText(c.getParameterExtraInfo())) {
                                break;
                            } else {
                                JSONObject j = JSON.parseObject(c.getParameterExtraInfo());
                                if("1".equals(j.getString("is_page"))) {

                                } else {
                                    break;
                                }
                            }
                        } else {
                            break;
                        }
                    }
                    if ("0".equals(properties.getString("is_page"))) {
                        IntrospectedColumn c = introspectedTable.getParameterColumns().get("sql."+sqlMethodName).get(0);
                        if (c != null) {
                            if(!StringUtils.hasText(c.getParameterExtraInfo())) {

                            } else {
                                JSONObject j = JSON.parseObject(c.getParameterExtraInfo());
                                if("0".equals(j.getString("is_page"))) {

                                } else {
                                    break;
                                }
                            }
                        } else {
                            break;
                        }
                    }
                    v = getName(token, sqlMethodName, properties, column, introspectedTable, dynTemplate);
                }while(false);
            } else if (isToken(token, "clear_line_when_global_prepare")) {
                result.setProcessed(true);
                Map<String, List<String>> globalPrepareMap = introspectedTable.getGlobalPrepareMap();
                String name = properties.getString("name");
                String isBlank = properties.getString("is_blank");
                if("1".equals(isBlank)) {
                    if(CollectionUtils.isEmpty(globalPrepareMap.get(name))) {
                        result.setClearLine(true);

                    }
                }
            } else if (isToken(token, "sql_param_name")) {
                result.setProcessed(true);
                if (StringUtils.isEmpty(sqlMethodName)) {
                    v = token + "<miss sql name>"+token;
                    continue;
                }
                List<IntrospectedColumn> oriColumns = introspectedTable.getParameterColumns().get("sql.param."+sqlMethodName);
                StringBuilder sbName = new StringBuilder();
                for(IntrospectedColumn paramItem: oriColumns) {
                    if (paramItem.getParameterNullable() == null || Integer.valueOf(1).equals(paramItem.getParameterNullable())) {
                        continue;
                    }
                    if (sbName.length() > 0) {
                        sbName.append("_");
                    }
                    sbName.append(getName(null, paramItem.getActualColumnName(), propertiesIsAjax, null, introspectedTable, dynTemplate));
                }
                v = getName(token, sbName.toString(), properties, column, introspectedTable, dynTemplate);
            } else if (isToken(token, "column_method_name")) {
                result.setProcessed(true);
                if (column == null) {
                    v = token + "<miss column>"+token;
                    continue;
                }
                v = getName(token, column.getParameterCatalogType(), properties, column, introspectedTable, dynTemplate);
            } else if (isToken(token, "column_name")) {
                result.setProcessed(true);
                if (column == null) {
                    v = token + "<miss column>"+token;
                    continue;
                }
                v = getName(token, column.getActualColumnName(), properties, column, introspectedTable, dynTemplate);
                if(properties.containsKey("is_replace_by_sql") && StringUtils.hasText(v)) {
                    if(prefixBytes != null && prefixBytes.pos > 0) {
                        String blanks = "";
                        for(int i = 0; i < prefixBytes.pos;i++) {
                            blanks += " ";
                        }
                        v = v.replaceAll("\n", "\n"+blanks);
                    }
                }
                if(properties.containsKey("is_replace_by_sqlparam") && StringUtils.hasText(v)) {
                    if(prefixBytes != null && prefixBytes.pos > 0) {
                        String blanks = "";
                        for(int i = 0; i < prefixBytes.pos;i++) {
                            blanks += " ";
                        }
                        v = v.replaceAll("\n", "\n"+blanks);
                    }
                }
            } else if (isToken(token, "package_name")) {
                result.setProcessed(true);
                v = getName(token, dynTemplate.getPackageName(), propertiesIsAjax, null, introspectedTable, dynTemplate);
            } else if (isToken(token, "auto_import_annotation")) {
                introspectedTable.setHasAutoImportAnnotation(true);
            } else if (isToken(token, "replace_by_sql")) {
                String name = properties.getString("name");
                result.setProcessed(true);
                v = null;
                IntrospectedColumn _replaceCol = cn.mysdp.utils.JavaBeansUtil.getReplaceTableIntrospectedColumn(introspectedTable);
                if(_replaceCol != null){
                    boolean _isExtraProcess = false;
                    if(StringUtils.hasText(_replaceCol.getParameterExtraInfo())) {
                        JSONObject extraInfo = JSON.parseObject(_replaceCol.getParameterExtraInfo());
                        if(extraInfo.containsKey("_project_"+introspectedTable.getDynProject().getName()+";"+name)) {
                            v = extraInfo.getString("_project_"+introspectedTable.getDynProject().getName()+";"+name);
                            _isExtraProcess = true;
                            if("import".equals(name) && !v.startsWith("import ")) {
                                v = "import "+v;
                            }
                            if("extends".equals(name) && !v.startsWith("extends ")) {
                                v = "extends "+v;
                            }
                        }
                    }
                    if(!_isExtraProcess) {
                        Map<String, String> replaceTableAnnotationMap = _replaceCol.getReplaceTableAnnotationMap();
                        if(replaceTableAnnotationMap.containsKey(name)) {
                            v = replaceTableAnnotationMap.get(name);
                        }
                    }
                }
            } else if (isToken(token, "project_root_path_tail")) {
                if (StringUtils.hasText(introspectedTable.getDynProject().getRootPath())) {
                    String pName = properties.getString("name");
                    String rootPath = introspectedTable.getDynProject().getRootPath();
                    if(StringUtils.hasText(pName)) {
                        SdpProjectQueryResponse _p = introspectedTable.getDynProjectMap().get(dynTemplate.getWorkspaceName()+";"+pName);
                        if(_p == null) {
                            throw new Exception("在处理project_root_path_tail时，未找到项目："+pName);
                        }
                        rootPath = _p.getRootPath();
                    }
                    String name = properties.getString("split");
                    if (StringUtils.hasText(rootPath) && StringUtils.hasText(name) && rootPath.indexOf(name) >= 0) {
                        v = rootPath.split(name)[1].replaceAll("/", ".").replaceAll("\\\\", ".");
                        while (v.startsWith(".")) {
                            v = v.substring(1);
                        }
                        while (v.endsWith(".")) {
                            v = v.substring(0, v.length() - 1);
                        }
                    } else {
                        v = "";
                    }
                } else {
                    v = "";
                }
            } else if (isToken(token, "project_extra_info_table")) {
                result.setProcessed(true);
                if(StringUtils.hasText(introspectedTable.getDynProject().getExtraInfo())) {
                    JSONObject extraInfo = JSON.parseObject(introspectedTable.getDynProject().getExtraInfo());
                    String name = properties.getString("name");
                    String value = extraInfo.getString("_table_"+introspectedTable.getFullyQualifiedTable().getIntrospectedTableName()+";"+name);
                    if(!StringUtils.hasText(value)) {
                        value = extraInfo.getString("_table_"+dynTemplate.getAliasTableName()+";"+name);
                    }
                    if(StringUtils.hasText(value)) {
                        String content = getCompilationUnits(dataSource, introspectedTable, value, dynTemplate, "", null, _processInstance, _processBodyToken, _processToken);
                        content = content.trim();
                        v = content;
                    } else {

                        v = "";
                    }
                } else {
                    v = "";
                }
                if(!StringUtils.hasText(v)) {
                    result.setIgnoreBlock(true);
                    v = null;
                }
            } else if (isToken(token, "project_extra_info")) {
                result.setProcessed(true);
                if(StringUtils.hasText(introspectedTable.getDynProject().getExtraInfo())) {
                    JSONObject extraInfo = JSON.parseObject(introspectedTable.getDynProject().getExtraInfo());
                    String name = properties.getString("name");
                    String value = extraInfo.getString(name);
                    if(StringUtils.hasText(value)) {
                        String content = getCompilationUnits(dataSource, introspectedTable, value, dynTemplate, "", null, _processInstance, _processBodyToken, _processToken);
                        content = content.trim();
                        v = content;
                    } else {
                        v = "";
                    }
                } else {
                    v = "";
                }
                if(!StringUtils.hasText(v)) {
                    result.setIgnoreBlock(true);
                    v = null;
                }
            } else if (isToken(token, "file_name")) {
                result.setProcessed(true);
                v = getName(token, fileName, propertiesIsAjax, null, introspectedTable, dynTemplate);
            } else if (isToken(token, "file_date")) {
                result.setProcessed(true);
                String fullFileName = introspectedTable.getDynProject().getRootPath();
                if (StringUtils.hasText(dynTemplate.getProject())) {
                    fullFileName += "/" + dynTemplate.getProject();
                }
                fullFileName += "/" + dynTemplate.getPackageName().replaceAll("\\.", "/") + "/" + fileName + "." + dynTemplate.getFileType();
                File file = new File(fullFileName);

                v = FileUtil.getOld(file.getAbsolutePath(), "* @Date:", null);
                result.setProcessed(true);
            } else if (isToken(token, "global_prepare")) {
                result.setProcessed(false);
                v = null;
            } else if (isToken(token, "config")) {
                result.setProcessed(true);
                String name = properties.getString("name");
                if ("workspace_db_host".equals(name)) {
                    v = ConnectUtil.getDatabaseHost(introspectedTable.getDynWorkspace(), dataSource.getConnection());
                } else if ("workspace_db_port".equals(name)) {
                    v = ConnectUtil.getDatabasePort(introspectedTable.getDynWorkspace(), dataSource.getConnection());
                } else if ("workspace_db_name".equals(name)) {
                    v = ConnectUtil.getDatabaseName(introspectedTable.getDynWorkspace(), dataSource.getConnection());
                } else if ("workspace_db_username".equals(name)) {
                    v = introspectedTable.getDynWorkspace().getDbUsername();
                } else if ("workspace_db_password".equals(name)) {
                    v = introspectedTable.getDynWorkspace().getDbPassword();
                } else {
                    try {
                        v = introspectedTable.getDynProject().getPropertyMap().get(name);
                        if(name.startsWith("package_") && !"1".equals(properties.getString("ignore_prefix_as_package_ending"))) {
                            String prefix_as_package_ending = cn.mysdp.utils.JavaBeansUtil.getJsonString(introspectedTable.getDynProject().getExtraInfo(), "prefix_as_package_ending");
                            if(StringUtils.hasText(prefix_as_package_ending)) {
                                String[] prefix_as_package_endings = prefix_as_package_ending.split(",");
                                for(String p: prefix_as_package_endings) {
                                    p = p.trim();
                                    String prefix = p;
                                    String endings = p;
                                    if(p.contains(" as ")) {
                                        String [] ps = p.split(" as ");
                                        prefix = ps[0].trim();
                                        endings = ps[1].trim();
                                    }
                                    String tName = dynTemplate.getAliasTableName();
                                    if(tName.startsWith(prefix+"_")) {
                                        v += "."+endings;
                                    }
                                }
                            }
                        }
                    }catch (Exception ex) {
                        ex.printStackTrace(System.err);
                        throw ex;
                    }
                }
                if (v == null) {
                    v = "<miss config>"+token+"/"+name;
                    continue;
                }
                if ("version".equals(name)) {
                    String fullFileName = introspectedTable.getDynProject().getRootPath();
                    if(StringUtils.hasText(dynTemplate.getProject())) {
                        fullFileName += "/" + dynTemplate.getProject();
                    }
                    fullFileName += "/" + dynTemplate.getPackageName().replaceAll("\\.", "/") + "/" + fileName + "." + dynTemplate.getFileType();
                    File file = new File(fullFileName);

                    v = FileUtil.getOld(file.getAbsolutePath(), "* @Version:", v);
                } else if ("author".equals(name)) {
                    String fullFileName = introspectedTable.getDynProject().getRootPath();
                    if(StringUtils.hasText(dynTemplate.getProject())) {
                        fullFileName += "/" + dynTemplate.getProject();
                    }
                    fullFileName += "/" + dynTemplate.getPackageName().replaceAll("\\.", "/") + "/" + fileName + "." + dynTemplate.getFileType();
                    File file = new File(fullFileName);

                    v = FileUtil.getOld(file.getAbsolutePath(), "* @Author:", v);
                }
            } else if (isToken(token, "serialVersionUID")) {
                result.setProcessed(true);
                v = Math.abs(dynTemplate.getPackageName().hashCode() / 100) + "" + Math.abs(fileName.hashCode());
            } else if (isToken(token, "table_comment")) {
                result.setProcessed(true);
                v = null;
                String name = "comment";
                String name2 = name;
                IntrospectedColumn _replaceCol = cn.mysdp.utils.JavaBeansUtil.getReplaceTableIntrospectedColumn(introspectedTable);
                if(_replaceCol != null){
                    boolean _isExtraProcess = false;
                    if(StringUtils.hasText(_replaceCol.getParameterExtraInfo())) {
                        JSONObject extraInfo = JSON.parseObject(_replaceCol.getParameterExtraInfo());
                        if(extraInfo.containsKey("_project_"+introspectedTable.getDynProject().getName()+";"+name)) {
                            v = extraInfo.getString("_project_"+introspectedTable.getDynProject().getName()+";"+name);
                            _isExtraProcess = true;
                        }
                    }
                    if(!_isExtraProcess) {
                        Map<String, String> replaceTableAnnotationMap = _replaceCol.getReplaceTableAnnotationMap();
                        if (replaceTableAnnotationMap.containsKey(name2)) {
                            v = replaceTableAnnotationMap.get(name2);
                        }
                    }
                } else {
                    System.out.println("debugger");
                }
                if(!StringUtils.hasText(v)) {
                    v = introspectedTable.getRemarks();
                }
            } else if (isToken(token, "value")) {
                result.setProcessed(true);
                v = properties.getString("value");
                if (v == null) {
                    v = "<miss value>" + token;
                    continue;
                }
            } else if (isToken(token, "column_import_java")) {
                result.setProcessed(true);
                if (column == null) {
                    v = "<miss column>"+token;
                    continue;
                }
                String _v = "";
                v = column.getFullyQualifiedJavaType().getFullyQualifiedName();
                if ("Date".equals(v)) {
                    v = "java.util.Date";
                }
                if (v.indexOf("List<") >= 0) {
                    v = "java.util.List";
                }
                if (v.indexOf("Map<") >= 0) {
                    v = "java.util.Map";
                } else if (v.indexOf("BigDecimal") >= 0) {
                    v = "java.math.BigDecimal";
                }
                if (v.indexOf(".") < 0) {
                    v = null;
                }

                String name = "type";
                String name2 = "_column:"+column.getActualColumnName()+":"+name;
                IntrospectedColumn _replaceCol = cn.mysdp.utils.JavaBeansUtil.getReplaceTableIntrospectedColumn(introspectedTable);
                if(_replaceCol != null){
                    boolean _isExtraProcess = false;
                    if(StringUtils.hasText(_replaceCol.getParameterExtraInfo())) {
                        JSONObject extraInfo = JSON.parseObject(_replaceCol.getParameterExtraInfo());
                        if(extraInfo.containsKey("_project_"+introspectedTable.getDynProject().getName()+";"+name)) {
                            v = extraInfo.getString("_project_"+introspectedTable.getDynProject().getName()+";"+name);
                        }
                    }
                    if(!_isExtraProcess) {
                        Map<String, String> replaceTableAnnotationMap = _replaceCol.getReplaceTableAnnotationMap();
                        if(replaceTableAnnotationMap.containsKey(name2)) {
                            v = replaceTableAnnotationMap.get(name2);
                        }
                    }
                    if(v.indexOf(".") < 0) {
                        v = null;
                    }
                }
                if(StringUtils.hasText(v)) {
                    v = "import "+v+";";
                }
            } else if (isToken(token, "column_java_type")) {
                result.setProcessed(true);
                if (column == null) {
                    v = "<miss column>"+token;
                    continue;
                }
                if ("1".equals(properties.getString("is_full_name"))) {
                    v = column.getFullyQualifiedJavaType().getFullyQualifiedName();
                    if ("Date".equals(v)) {
                        v = "java.util.Date";
                    } else if (v.startsWith("List<")) {
                        v = "java.util.List";
                    } else if (v.startsWith("Map<")) {
                        v = "java.util.Map";
                    } else if ("BigDecimal".equals(v)) {
                        v = "java.math.BigDecimal";
                    }
                    if (v.indexOf(".") < 0) {
                        v = null;
                        continue;
                    }
                } else {
                    v = column.getFullyQualifiedJavaType().getShortName();
                }

                String name = "type";
                String name2 = "_column:"+column.getActualColumnName()+":"+name;
                IntrospectedColumn _replaceCol = cn.mysdp.utils.JavaBeansUtil.getReplaceTableIntrospectedColumn(introspectedTable);
                if(_replaceCol != null){
                    boolean _isExtraProcess = false;
                    if(StringUtils.hasText(_replaceCol.getParameterExtraInfo())) {
                        JSONObject extraInfo = JSON.parseObject(_replaceCol.getParameterExtraInfo());
                        if(extraInfo.containsKey("_project_"+introspectedTable.getDynProject().getName()+";"+name)) {
                            v = extraInfo.getString("_project_"+introspectedTable.getDynProject().getName()+";"+name);
                            _isExtraProcess = true;
                        }
                    }
                    if(!_isExtraProcess) {
                        Map<String, String> replaceTableAnnotationMap = _replaceCol.getReplaceTableAnnotationMap();
                        if (replaceTableAnnotationMap.containsKey(name2)) {
                            v = replaceTableAnnotationMap.get(name2);
                        }
                    }
                }
            } else if (isToken(token, "column_java_return_type")) {
                result.setProcessed(true);
                if (column == null) {
                    v = "<miss column>"+token;
                    continue;
                }
                v = column.getParameterJavaReturnType();
            } else if (isToken(token, "column_java_imports")) {
                result.setProcessed(true);
                if (column == null) {
                    v = "<miss column>"+token;
                    continue;
                }
                if (!StringUtility.stringHasValue(column.getParameterImports())) {
                    continue;
                }
                List<String> vsLines = SplitUtil.splitLines(column.getParameterImports());
                v = "";
                for (String vLine : vsLines) {
                    vLine = vLine.replaceAll("\n", "").replaceAll("\r", "");
                    String[] vImports = vLine.split(";");
                    for (String vImport : vImports) {
                        vImport = vImport.trim();
                        if (!StringUtility.stringHasValue(vImport)) {
                            continue;
                        }
                        if (vImport.startsWith("import ")) {
                            vImport = vImport.replace("import ", "").trim();
                        }
                        if (!"".equals(v)) {
                            v += System.lineSeparator();
                        }
                        v += "import " + vImport + ";";
                    }
                }
            } else if (isToken(token, "column_sql")) {
                result.setProcessed(true);
                if (column == null) {
                    v = "<miss column>"+token;
                    continue;
                }
                v = column.getParameterSql();
            } else if (isToken(token, "column_ori_sql")) {
                result.setProcessed(true);
                if (column == null) {
                    v = "<miss column>"+token;
                    continue;
                }
                v = column.getParameterOriSql();
                int loop = 0;
                while(v.indexOf("--") >= 0 && loop++<100) {
                    v = v.replaceAll("--", "－－");
                }
            } else if (isToken(token, "column_simple_sql")) {
                result.setProcessed(true);
                if (column == null) {
                    v = "<miss column>"+token;
                    continue;
                }
                v = column.getParameterSimpleSql();
            } else if (isToken(token, "column_simple_sql_with_star")) {
                result.setProcessed(true);
                if (column == null) {
                    v = "<miss column>" + token;
                    continue;
                }
                v = column.getParameterSimpleWithStarSql();
            } else if (isToken(token, "column_index")) {
                v = columnIndex + "";
            } else if (isToken(token, "column_comment")) {
                result.setProcessed(true);
                if (column == null) {
                    v = "<miss column>"+token;
                    continue;
                }

                v = null;
                String name = "comment";
                String name2 = "_column:"+column.getActualColumnName()+":"+name;
                IntrospectedColumn _replaceCol = cn.mysdp.utils.JavaBeansUtil.getReplaceTableIntrospectedColumn(introspectedTable);
                if(_replaceCol != null){
                    boolean _isExtraProcess = false;
                    if(StringUtils.hasText(_replaceCol.getParameterExtraInfo())) {
                        JSONObject extraInfo = JSON.parseObject(_replaceCol.getParameterExtraInfo());
                        if(extraInfo.containsKey("_project_"+introspectedTable.getDynProject().getName()+";"+name)) {
                            v = extraInfo.getString("_project_"+introspectedTable.getDynProject().getName()+";"+name);
                            _isExtraProcess = true;
                        }
                    }
                    if(!_isExtraProcess) {
                        Map<String, String> replaceTableAnnotationMap = _replaceCol.getReplaceTableAnnotationMap();
                        if (replaceTableAnnotationMap.containsKey(name2)) {
                            v = replaceTableAnnotationMap.get(name2);
                        }
                    }
                }
                if(!StringUtils.hasText(v)) {
                    if(_replaceCol != null){
                        Map<String, Map<String, String>> fieldInfoMap = _replaceCol.getFieldInfoMap();
                        String dbName = introspectedTable.getFullyQualifiedTable().getIntrospectedCatalog();
                        if(!StringUtils.hasText(dbName)) {
                            dbName = introspectedTable.getFullyQualifiedTable().getIntrospectedSchema();
                        }
                        String tName = introspectedTable.getFullyQualifiedTable().getIntrospectedTableName();
                        if(fieldInfoMap.containsKey(dbName + "." + tName + "." + column.getActualColumnName())) {
                            Map<String, String> fieldsMap = fieldInfoMap.get(dbName + "." + tName + "." + column.getActualColumnName());
                            if(introspectedTable.getIntrospectedTableMap().containsKey(fieldsMap.get("databaseName")+"."+fieldsMap.get("databaseName")+"."+fieldsMap.get("originalTableName"))) {
                                IntrospectedTable _introspectedTable = introspectedTable.getIntrospectedTableMap().get(fieldsMap.get("databaseName")+"."+fieldsMap.get("databaseName")+"."+fieldsMap.get("originalTableName"));
                                for(IntrospectedColumn _col: _introspectedTable.getAllColumns()) {
                                    if(fieldsMap.get("originalColumnName").equals(fieldsMap.get("columnName"))
                                            && fieldsMap.get("originalTableName") != null && fieldsMap.get("tableName") != null && fieldsMap.get("originalTableName").equals(fieldsMap.get("tableName"))
                                    ) {
                                        continue;
                                    }
                                    if(_col.getActualColumnName().equals(fieldsMap.get("originalColumnName"))) {
                                        v = _col.getRemarks();
                                    }
                                }
                            }
                        }
                    }
                }
                if(!StringUtils.hasText(v)) {
                    v = column.getRemarks();
                }
            } else if (isToken(token, "column_param_for_repository")) {
                result.setProcessed(true);
                if (column == null) {
                    v = "<miss column>"+token;
                    continue;
                }
                v = column.getUniqueKeyparameterForRepository();
            } else if (isToken(token, "column_name_for_repository")) {
                result.setProcessed(true);
                if (column == null) {
                    v = "<miss column>"+token;
                    continue;
                }
                v = column.getUniqueKeynameForRepository();
                v = getName(null, v, properties, null, introspectedTable, dynTemplate);
            } else if (isToken(token, "column_name_dash_for_repository")) {
                result.setProcessed(true);
                if (column == null) {
                    v = "<miss column>"+token;
                    continue;
                }
                v = column.getUniqueKeynameDash();
            } else if (isToken(token, "column_parameter_type_for_mapper")) {
                result.setProcessed(true);
                if (column == null) {
                    v = "<miss column>"+token;
                    continue;
                }
                v = column.getUniqueKeytypeForMapper();
            }
        }while(false);
        if (!StringUtils.isEmpty(v)) {
            if ("1".equals(properties.getString("trim"))) {
                v = v.trim();
            }
            if("1".equals(properties.getString("is_dup_prefix"))) {
                if(prefixBytes != null && prefixBytes.pos > 0) {
                    String prefix = prefixBytes.toString();
                    v = v.replaceAll("\n", "\n"+prefix);
                }
            }
        }

        if (StringUtils.hasText(v) && properties.containsKey("result_contains")) {
            String _s = properties.getString("result_contains");
            if(!v.contains(_s)) {
                v = null;
            }
        }

        if (StringUtils.hasText(v) && "1".equals(properties.getString("is_primary_key"))) {
            if(!introspectedTable.isPrimaryKey(column.getActualColumnName())) {
                v = null;
            }
        }

        if (StringUtils.hasText(v) && "0".equals(properties.getString("is_primary_key"))) {
            if(introspectedTable.isPrimaryKey(column.getActualColumnName())) {
                v = null;
            }
        }

        if(StringUtils.hasText(v) && properties.containsKey("is_replace_by_value")) {
            v = properties.getString("is_replace_by_value");
        }

        if(StringUtils.hasText(v) && properties.containsKey("is_replace_by_value")) {
            if(prefixBytes != null && prefixBytes.pos > 0 && StringUtils.hasText(prefixBytes.toString())) {
                String blanks = "";
                for(int i = 0; i < prefixBytes.pos;i++) {
                    blanks += " ";
                }
                v = v.replaceAll("\n", "\n"+blanks);
            }
        }

        if(StringUtils.hasText(v) && properties.containsKey("is_nullable")) {
            if (column != null) {

                if((column.getParameterNullable() == null || Integer.valueOf(1).equals(column.getParameterNullable())) && "0".equals(properties.getString("is_nullable"))) {
                    v = null;
                } else if (Integer.valueOf(0).equals(column.getParameterNullable()) && "1".equals(properties.getString("is_nullable"))) {
                    v = null;
                }
            }
        }
        if (StringUtils.hasText(v) && "1".equals(properties.getString("only_first_lower"))) {
            StringBuilder sb = new StringBuilder();
            sb.append(v);
            sb.setCharAt(0, Character.toLowerCase(sb.charAt(0)));
            v = sb.toString();
        }

        if(!StringUtils.hasText(v)) {
            if("1".equals(properties.getString("empty_as_lower_camel_column_name"))
                    || "1".equals(properties.getString("empty_as_upper_camel_column_name"))
                    || "1".equals(properties.getString("empty_as_lower_snake_column_name"))
                    || "1".equals(properties.getString("empty_as_upper_snake_column_name"))
            ) {
                if(column == null) {
                    throw new Exception("未在columns块中，无法分析column.name");
                }
                try {
                    v = getName(token, column.getActualColumnName(), properties, column, introspectedTable, dynTemplate);
                }catch (Exception ex) {
                    ex.printStackTrace(System.err);
                    throw ex;
                }
            }
            if("1".equals(properties.getString("empty_as_lower_camel_table_name"))
                    || "1".equals(properties.getString("empty_as_lower_camel_alias_table_name"))
                    || "1".equals(properties.getString("empty_as_upper_camel_table_name"))
                    || "1".equals(properties.getString("empty_as_upper_camel_alias_table_name"))
                    || "1".equals(properties.getString("empty_as_lower_snake_table_name"))
                    || "1".equals(properties.getString("empty_as_lower_snake_alias_table_name"))
                    || "1".equals(properties.getString("empty_as_upper_snake_table_name"))
                    || "1".equals(properties.getString("empty_as_upper_snake_alias_table_name"))
            ) {
                v = getName(token, introspectedTable.getTableConfiguration().getTableName(), properties, column, introspectedTable, dynTemplate);
            }
        }

        if(StringUtils.hasText(v)) {
            if ("1".equals(properties.getString("is_first_line"))) {
                v = cn.mysdp.utils.JavaBeansUtil.getFirstLine(v);
                if(!StringUtils.hasText(v)) {
                    System.out.println("debugger");
                }
            }
        }

        result.setResult(v);
        if (!StringUtils.isEmpty(v)) {
            result.setProcessed(true);
        }
        if(properties.containsKey("global_prepare")) {
            String name = properties.getString("global_prepare");
            if(!introspectedTable.getGlobalPrepareMap().containsKey(name)) {
                introspectedTable.getGlobalPrepareMap().put(name, new ArrayList<>());
            }
            if(StringUtils.hasText(v)) {
                if("1".equals(properties.getString("is_auto_import"))) {
                    String[] _vs = v.split("\n");
                    for(String _v:_vs) {
                        _v = _v.trim();
                        if(_v.startsWith("@")) {
                            String _key = _v.substring(1).split("\\(")[0];
                            Map<String, String> autoImportAnnotationMap = introspectedTable.getAutoImportAnnotationMap();
                            if(autoImportAnnotationMap != null && autoImportAnnotationMap.containsKey(_key)) {
                                String _s = autoImportAnnotationMap.get(_key);
                                if(!cn.mysdp.utils.JavaBeansUtil.contains(introspectedTable.getGlobalPrepareMap().get(name), _s)) {
                                    introspectedTable.getGlobalPrepareMap().get(name).add(_s);
                                }
                            }
                        }
                    }
                } else {
                    if(!cn.mysdp.utils.JavaBeansUtil.contains(introspectedTable.getGlobalPrepareMap().get(name), v)) {
                        introspectedTable.getGlobalPrepareMap().get(name).add(v);
                    }
                }
                if(isToken(token, "column_import_java")) {
                    v = column.getParameterImports();
                    if(StringUtils.hasText(v)) {
                        String[] _vs = v.split("\n");
                        for(String _s:_vs) {
                            _s = _s.trim();
                            if(!cn.mysdp.utils.JavaBeansUtil.contains(introspectedTable.getGlobalPrepareMap().get(name), _s)) {
                                introspectedTable.getGlobalPrepareMap().get(name).add(_s);
                            }
                        }
                    }
                }
            }
            result.setResult(null);
        }
        return result;
    }

    private JSONObject processStarProperties(String vTrim) {
        JSONObject map = new JSONObject();
        vTrim = vTrim.substring(0, vTrim.length() - 1);
        String[] properties = vTrim.split("&");
        if (properties.length > 1) {
            for(int i = 1; i < properties.length; i++) {
                int pos = properties[i].indexOf("=");
                if (pos > 0) {
                    if (pos < properties[i].length() - 1) {
                        map.put(properties[i].substring(0, pos).trim(), properties[i].substring(pos+1));
                    } else {
                        map.put(properties[i].substring(0, pos).trim(), "");
                    }
                } else {
                    map.put(properties[i].trim(), "");
                }
            }
        }
        return map;
    }

    public List<IntrospectedColumn> fixIntrospectedColumns(IntrospectedTable introspectedTable, SdpTemplateQueryResponse dynTemplate, List<IntrospectedColumn> introspectedColumns, JSONObject properties, Map<String, IntrospectedColumn> sqlParamNameMap, String fileName, String sqlMethodName) {
        Set<String> processedPropertiesSet = new HashSet<>();
        processedPropertiesSet.add("has_blobs");
        processedPropertiesSet.add("has_primary_key");
        processedPropertiesSet.add("has_auto_increment");
        processedPropertiesSet.add("column_is_first");
        processedPropertiesSet.add("column_is_last");
        processedPropertiesSet.add("only_primary_key");
        processedPropertiesSet.add("is_only_param_columns");
        processedPropertiesSet.add("is_only_request_columns");
        processedPropertiesSet.add("is_only_response_columns");
        processedPropertiesSet.add("is_only_miss_extra_request_columns");
        processedPropertiesSet.add("is_only_miss_extra_response_columns");
        processedPropertiesSet.add("is_no_extra_request_columns");
        processedPropertiesSet.add("is_no_extra_response_columns");
        processedPropertiesSet.add("is_both_request_columns");
        processedPropertiesSet.add("is_both_response_columns");
        processedPropertiesSet.add("include_param_columns");
        processedPropertiesSet.add("include_request_columns");
        processedPropertiesSet.add("include_response_columns");
        processedPropertiesSet.add("extra_request_columns");
        processedPropertiesSet.add("extra_response_columns");
        processedPropertiesSet.add("empty_as_table");
        processedPropertiesSet.add("content_id");
        processedPropertiesSet.add("is_empty_content");
        processedPropertiesSet.add("not_empty_as_empty");
        processedPropertiesSet.add("is_replace_by_sql");
        processedPropertiesSet.add("is_replace_by_sqlparam");
        processedPropertiesSet.add("include_all_sql_param");
        processedPropertiesSet.add("is_fix_dup");

        String currentProperty = "has_columns_1";
        processedPropertiesSet.add(currentProperty);
        if (properties.getString(currentProperty) != null) {
            Map<String, IntrospectedColumn> doneSet = new HashMap<>();

            List<IntrospectedColumn> introspectedColumns1 = new ArrayList<>();

            for(IntrospectedColumn column: introspectedColumns) {
                doneSet.put(column.getActualColumnName(), column);
            }

            String[] hasColumnNames = properties.getString(currentProperty).split(",");
            for(String name: hasColumnNames) {
                name = name.trim();
                if (StringUtils.isEmpty(name)) {
                    continue;
                }
                if (doneSet.containsKey(name)) {
                    introspectedColumns1.add(doneSet.get(name));
                    return introspectedColumns1;
                }
            }
            return introspectedColumns1;
        }

        currentProperty = "has_dup";
        processedPropertiesSet.add(currentProperty);
        if ("1".equals(properties.getString(currentProperty)+"")) {
            if(!CollectionUtils.isEmpty(introspectedColumns)) {
                List<IntrospectedColumn> introspectedColumns1 = new ArrayList<>();

                boolean hasDup = false;
                for(IntrospectedColumn column: introspectedColumns) {
                    if(column.getDup()) {
                        hasDup = true;
                    }
                }
                if(hasDup) {
                    introspectedColumns1.add(introspectedColumns.get(0));
                }
                return introspectedColumns1;
            } else {
                return new ArrayList<>();
            }
        } else if ("0".equals(properties.getString(currentProperty)+"")) {
            if(!CollectionUtils.isEmpty(introspectedColumns)) {
                List<IntrospectedColumn> introspectedColumns1 = new ArrayList<>();

                boolean hasDup = false;
                for(IntrospectedColumn column: introspectedColumns) {
                    if(column.getDup()) {
                        hasDup = true;
                    }
                }
                if(!hasDup) {
                    introspectedColumns1.add(introspectedColumns.get(0));
                }
                return introspectedColumns1;
            } else {
                return new ArrayList<>();
            }
        }

        currentProperty = "has_columns_0";
        processedPropertiesSet.add(currentProperty);
        if (properties.getString(currentProperty) != null) {
            Set<String> doneSet = new HashSet<>();

            List<IntrospectedColumn> introspectedColumns1 = new ArrayList<>();

            for(IntrospectedColumn column: introspectedColumns) {
                doneSet.add(column.getActualColumnName());
            }

            String[] hasColumnNames = properties.getString(currentProperty).split(",");
            for(String name: hasColumnNames) {
                name = name.trim();
                if (StringUtils.isEmpty(name)) {
                    continue;
                }
                if (doneSet.contains(name)) {
                    return introspectedColumns1;
                }
            }
            if (!CollectionUtils.isEmpty(introspectedColumns)) {
                introspectedColumns1.add(introspectedColumns.get(0));
            }
            return introspectedColumns1;
        }

        currentProperty = "discard";
        processedPropertiesSet.add(currentProperty);
        Set<String> discardSet = new HashSet<>();
        if (properties.containsKey(currentProperty)) {
            for(String name: properties.getString(currentProperty).split(",")) {
                discardSet.add(name.trim());
            }
        }

        currentProperty = "is_empty_content";
        processedPropertiesSet.add(currentProperty);
        Set<String> emptyContentSet = new HashSet<>();
        if (properties.containsKey(currentProperty)) {
            for(String name: properties.getString(currentProperty).split(",")) {
                emptyContentSet.add(name.trim());
            }
        }

        currentProperty = "is_not_empty_content";
        processedPropertiesSet.add(currentProperty);
        Set<String> notEmptyContentSet = new HashSet<>();
        if (properties.containsKey(currentProperty)) {
            for(String name: properties.getString(currentProperty).split(",")) {
                notEmptyContentSet.add(name.trim());
            }
        }

        currentProperty = "has_columns";
        processedPropertiesSet.add(currentProperty);
        Set<String> hasColumnsSet = new HashSet<>();
        if (properties.containsKey(currentProperty)) {
            for(String name: properties.getString(currentProperty).split(",")) {
                hasColumnsSet.add(name.trim());
            }
        }

        Set<String> doneSet = new HashSet<>();

        List<IntrospectedColumn> introspectedColumns1 = new ArrayList<>();

        Set<String> hasIsSet = new HashSet<>();

        currentProperty = "is_dup";
        processedPropertiesSet.add(currentProperty);
        if ("1".equals(properties.getString(currentProperty))) {
            hasIsSet.add(currentProperty);
        }

        for(IntrospectedColumn column: introspectedColumns) {
            Set<String> localHasIsSet = new HashSet<>();

            if ("1".equals(properties.getString("is_dup"))) {
                localHasIsSet.add("is_dup");
            }

            if (doneSet.contains(column.getActualColumnName()) && !"0".equals(properties.getString("is_fix_dup"))) {
                continue;
            }
            if (discardSet.contains(column.getActualColumnName())) {
                continue;
            }
            {
                boolean needContinue = false;
                for(String contentId: emptyContentSet) {
                    if(StringUtils.hasText((String) introspectedTable.getDynWorkspace().getExtraMap().get(contentId))) {
                        needContinue = true;
                        break;
                    }
                }
                if(needContinue) {
                    continue;
                }
            }

            {
                boolean needContinue = false;
                for(String contentId: notEmptyContentSet) {
                    if(!StringUtils.hasText((String) introspectedTable.getDynWorkspace().getExtraMap().get(contentId))) {
                        needContinue = true;
                        break;
                    }
                }
                if(needContinue) {
                    continue;
                }
            }

            if (hasColumnsSet.size() > 0 && !hasColumnsSet.contains(column.getActualColumnName())) {
                continue;
            }
            doneSet.add(column.getActualColumnName());

            currentProperty = "column_name";
            processedPropertiesSet.add(currentProperty);
            if (!StringUtils.isEmpty(properties.getString(currentProperty))) {
                if (!properties.getString(currentProperty).equals(column.getActualColumnName())) {
                    continue;
                }
            }

            currentProperty = "is_simple";
            processedPropertiesSet.add(currentProperty);
            if ("1".equals(properties.getString(currentProperty))) {
                if (Integer.valueOf(1).equals(column.getParameterSqlIsSimple())) {
                    hasIsSet.add(currentProperty);
                    localHasIsSet.add(currentProperty);
                } else {
                    continue;
                }
            }
            if ("0".equals(properties.getString(currentProperty))) {
                if (Integer.valueOf(1).equals(column.getParameterSqlIsSimple())) {
                    continue;
                }
            }

            currentProperty = "is_interface";
            processedPropertiesSet.add(currentProperty);
            if ("1".equals(properties.getString(currentProperty))) {
                if (Integer.valueOf(1).equals(column.getSqlIsInterface())) {
                    hasIsSet.add(currentProperty);
                    localHasIsSet.add(currentProperty);
                } else {
                    continue;
                }
            }
            if ("0".equals(properties.getString(currentProperty))) {
                if (Integer.valueOf(1).equals(column.getSqlIsInterface())) {
                    continue;
                }
            }

            currentProperty = "is_string";
            processedPropertiesSet.add(currentProperty);
            if ("1".equals(properties.getString(currentProperty))) {
                if ("String".equals(column.getFullyQualifiedJavaType().getShortName())
                        || column.isStringColumn()
                ) {
                    hasIsSet.add(currentProperty);
                    localHasIsSet.add(currentProperty);
                } else {
                    continue;
                }
            }
            if ("0".equals(properties.getString(currentProperty))) {
                if ("String".equals(column.getFullyQualifiedJavaType().getShortName())
                        || column.isStringColumn()
                ) {
                    continue;
                } else {
                }
            }

            currentProperty = "is_integer";
            processedPropertiesSet.add(currentProperty);
            if ("1".equals(properties.getString(currentProperty))) {
                if ("Integer".equals(column.getFullyQualifiedJavaType().getShortName())) {
                    hasIsSet.add(currentProperty);
                    localHasIsSet.add(currentProperty);
                } else {
                    continue;
                }
            }
            if ("0".equals(properties.getString(currentProperty))) {
                if ("Integer".equals(column.getFullyQualifiedJavaType().getShortName())) {
                    continue;
                }
            }

            currentProperty = "is_long";
            processedPropertiesSet.add(currentProperty);
            if ("1".equals(properties.getString(currentProperty))) {
                if ("Long".equals(column.getFullyQualifiedJavaType().getShortName())) {
                    hasIsSet.add(currentProperty);
                    localHasIsSet.add(currentProperty);
                } else {
                    continue;
                }
            }
            if ("0".equals(properties.getString(currentProperty))) {
                if ("Long".equals(column.getFullyQualifiedJavaType().getShortName())) {
                    continue;
                }
            }

            currentProperty = "is_big_decimal";
            processedPropertiesSet.add(currentProperty);
            if ("1".equals(properties.getString(currentProperty))) {
                if ("BigDecimal".equals(column.getFullyQualifiedJavaType().getShortName())) {
                    hasIsSet.add(currentProperty);
                    localHasIsSet.add(currentProperty);
                } else {
                    continue;
                }
            }
            if ("0".equals(properties.getString(currentProperty))) {
                if ("BigDecimal".equals(column.getFullyQualifiedJavaType().getShortName())) {
                    continue;
                }
            }

            currentProperty = "is_date";
            processedPropertiesSet.add(currentProperty);
            if ("1".equals(properties.getString(currentProperty))) {
                if ("Date".equals(column.getFullyQualifiedJavaType().getShortName())
                        || column.isJDBCDateColumn()
                ) {
                    hasIsSet.add(currentProperty);
                    localHasIsSet.add(currentProperty);
                } else {
                    continue;
                }
            }
            if ("0".equals(properties.getString(currentProperty))) {
                if ("Date".equals(column.getFullyQualifiedJavaType().getShortName())
                        || column.isJDBCDateColumn()
                ) {
                    continue;
                }
            }

            currentProperty = "is_blob";
            processedPropertiesSet.add(currentProperty);
            if ("1".equals(properties.getString(currentProperty))) {
                if (column.isBLOBColumn()) {
                    hasIsSet.add(currentProperty);
                    localHasIsSet.add(currentProperty);
                } else {
                    continue;
                }
            }
            if ("0".equals(properties.getString(currentProperty))) {
                if (column.isBLOBColumn()) {
                    continue;
                }
            }

            currentProperty = "is_primary_key";
            processedPropertiesSet.add(currentProperty);
            if ("1".equals(properties.getString(currentProperty))) {
                if(introspectedTable.isPrimaryKey(column.getActualColumnName())) {
                    hasIsSet.add(currentProperty);
                    localHasIsSet.add(currentProperty);
                } else {
                    continue;
                }
            }
            if ("0".equals(properties.getString(currentProperty))) {
                if(introspectedTable.isPrimaryKey(column.getActualColumnName())) {
                    continue;
                }
            }

            currentProperty = "is_primary_key_multiple";
            processedPropertiesSet.add(currentProperty);
            if ("1".equals(properties.getString(currentProperty))) {
                if (!CollectionUtils.isEmpty(introspectedTable.getPrimaryKeyColumns()) && introspectedTable.getPrimaryKeyColumns().size() > 1) {
                    hasIsSet.add(currentProperty);
                    localHasIsSet.add(currentProperty);
                } else {
                    continue;
                }
            }
            if ("0".equals(properties.getString(currentProperty))) {
                if (!CollectionUtils.isEmpty(introspectedTable.getPrimaryKeyColumns()) && introspectedTable.getPrimaryKeyColumns().size() > 1) {
                    continue;
                }
            }

            currentProperty = "is_auto_increment";
            processedPropertiesSet.add(currentProperty);
            if ("1".equals(properties.getString(currentProperty))) {
                if(column.isAutoIncrement()){
                    hasIsSet.add(currentProperty);
                    localHasIsSet.add(currentProperty);
                } else{
                    continue;
                }
            }
            if ("0".equals(properties.getString(currentProperty))) {
                if(column.isAutoIncrement()){
                    continue;
                }
            }

            currentProperty = "is_import_excel";
            processedPropertiesSet.add(currentProperty);
            if ("1".equals(properties.getString(currentProperty))) {
                if (Integer.valueOf(1).equals(column.getParameterIsImportExcel())) {
                    hasIsSet.add(currentProperty);
                    localHasIsSet.add(currentProperty);
                } else {
                    continue;
                }
            }
            if ("0".equals(properties.getString(currentProperty))) {
                if (Integer.valueOf(1).equals(column.getParameterIsImportExcel())) {
                    continue;
                }
            }

            if (Boolean.valueOf(true).equals(column.getDup())) {
                if ("1".equals(properties.getString("is_dup"))) {
                } else {
                    continue;
                }
            }

            currentProperty = "param_is_nullable";
            processedPropertiesSet.add(currentProperty);
            if ("1".equals(properties.getString(currentProperty))) {
                if (sqlParamNameMap.containsKey(column.getActualColumnName())) {
                    IntrospectedColumn parameterColumn = sqlParamNameMap.get(column.getActualColumnName());
                    if (parameterColumn.getParameterNullable() == null || Integer.valueOf(1).equals(parameterColumn.getParameterNullable())) {
                        hasIsSet.add(currentProperty);
                        localHasIsSet.add(currentProperty);
                    } else {
                        continue;
                    }
                } else {
                    continue;
                }
            }
            if ("0".equals(properties.getString(currentProperty))) {
                if (sqlParamNameMap.containsKey(column.getActualColumnName())) {
                    IntrospectedColumn parameterColumn = sqlParamNameMap.get(column.getActualColumnName());
                    if (parameterColumn.getParameterNullable() == null || Integer.valueOf(1).equals(parameterColumn.getParameterNullable())) {
                        continue;
                    }
                }
            }

            currentProperty = "param_is_like";
            processedPropertiesSet.add(currentProperty);
            if ("1".equals(properties.getString(currentProperty))) {
                if (sqlParamNameMap.containsKey(column.getActualColumnName())) {
                    IntrospectedColumn parameterColumn = sqlParamNameMap.get(column.getActualColumnName());
                    if (Integer.valueOf(1).equals(parameterColumn.getParameterIsLike())) {
                        hasIsSet.add("is_like_param");
                        localHasIsSet.add("is_like_param");
                    } else {
                        continue;
                    }
                } else {
                    continue;
                }
            }
            if ("0".equals(properties.getString(currentProperty))) {
                if (sqlParamNameMap.containsKey(column.getActualColumnName())) {
                    IntrospectedColumn parameterColumn = sqlParamNameMap.get(column.getActualColumnName());
                    if (Integer.valueOf(1).equals(parameterColumn.getParameterIsLike())) {
                        continue;
                    }
                }
            }

            currentProperty = "has_column_java_imports";
            processedPropertiesSet.add(currentProperty);
            if ("1".equals(properties.getString(currentProperty))) {
                if (StringUtility.stringHasValue(column.getParameterImports())) {
                    hasIsSet.add(currentProperty);
                    localHasIsSet.add(currentProperty);
                } else {
                    continue;
                }
            }
            if ("0".equals(properties.getString(currentProperty))) {
                if (StringUtility.stringHasValue(column.getParameterImports())) {
                    continue;
                }
            }

            currentProperty = "has_java_return_type";
            processedPropertiesSet.add(currentProperty);
            if ("1".equals(properties.getString(currentProperty))) {
                if (StringUtility.stringHasValue(column.getParameterJavaReturnType())) {
                    hasIsSet.add(currentProperty);
                    localHasIsSet.add(currentProperty);
                } else {
                    continue;
                }
            }
            if ("0".equals(properties.getString(currentProperty))) {
                if (StringUtility.stringHasValue(column.getParameterJavaReturnType())) {
                    continue;
                }
            }

            currentProperty = "has_java_field_type_with_package";
            processedPropertiesSet.add(currentProperty);
            if ("1".equals(properties.getString(currentProperty))) {

                String v = column.getFullyQualifiedJavaType().getFullyQualifiedName();
                if ("Date".equals(v)) {
                    v = "java.util.Date";
                } else if (v.startsWith("List<")) {
                    v = "java.util.List";
                } else if (v.startsWith("Map<")) {
                    v = "java.util.Map";
                }

                if (v.indexOf(".") >= 0) {
                    if (!v.startsWith("java.lang.")) {
                    } else {
                        continue;
                    }
                } else {
                    continue;
                }
            }
            if ("0".equals(properties.getString(currentProperty))) {
                String v = column.getFullyQualifiedJavaType().getFullyQualifiedName();
                if ("Date".equals(v)) {
                    v = "java.util.Date";
                } else if (v.startsWith("List<")) {
                    v = "java.util.List";
                } else if (v.startsWith("Map<")) {
                    v = "java.util.Map";
                }

                if (v.indexOf(".") >= 0) {
                    if (!v.startsWith("java.lang.")) {
                        continue;
                    }
                }
            }

            if (!StringUtils.isEmpty(column.getParameterExtraInfo())) {
                try {
                    JSONObject extraInfo = JSON.parseObject(column.getParameterExtraInfo());
                    boolean needIgnore = false;
                    for(String p : extraInfo.keySet()) {
                        if ("1".equals(extraInfo.get(p) + "") && p.startsWith("is_")) {
                            hasIsSet.add(p);
                            localHasIsSet.add(p);
                        }
                        if (StringUtils.isEmpty(properties.getString(p))) {
                            continue;
                        }
                        if (!properties.getString(p).equals(extraInfo.get(p) + "")) {
                            needIgnore = true;
                            System.out.println("=================");
                            System.out.println("2698");
                            System.out.println("ignore for:"+p);
                            break;
                        }
                    }
                    if (!needIgnore) {
                        for(String key: properties.keySet()) {
                            if (processedPropertiesSet.contains(key)) {
                                continue;
                            }
                            if ("1".equals(properties.getString(key))) {
                                if ("1".equals(extraInfo.get(key)+"")) {

                                } else {
                                    needIgnore = true;
                                    System.out.println("=================");
                                    System.out.println("2714");
                                    System.out.println("ignore for:"+key);
                                }
                            } else if ("0".equals(properties.getString(key))) {
                                if ("1".equals(extraInfo.get(key)+"")) {
                                    needIgnore = true;
                                    System.out.println("=================");
                                    System.out.println("2721");
                                    System.out.println("ignore for:"+key);
                                }
                            }
                        }
                    }
                    if (needIgnore) {
                        continue;
                    }
                }catch(Exception ex) {
                    ex.printStackTrace(System.err);
                    System.err.println("invalid extra info:"+column.getParameterExtraInfo());
                }
            } else {
                boolean needIgnore = false;
                for(String key: properties.keySet()) {
                    if (processedPropertiesSet.contains(key)) {
                        continue;
                    }
                    if ("1".equals(properties.getString(key))) {
                        needIgnore = true;
                        System.out.println("=================");
                        System.out.println("2743");
                        System.out.println("ignore for:"+key);
                    }
                }
                if (needIgnore) {
                    continue;
                }
            }

            introspectedColumns1.add(column);
        }

        for(String p : properties.keySet()) {
            if (p.startsWith("has_is_")) {
                String pp = p.substring("has_".length());
                if ("1".equals(properties.getString(p))) {
                    if (!hasIsSet.contains(pp)) {
                        introspectedColumns1 = new ArrayList<>();
                        break;
                    }
                } else {
                    if (hasIsSet.contains(pp)) {
                        introspectedColumns1 = new ArrayList<>();
                        break;
                    }
                    if (CollectionUtils.isEmpty(introspectedColumns1)) {
                        IntrospectedColumn newColumn = new IntrospectedColumn();
                        newColumn.setContext(introspectedTable.getContext());
                        introspectedColumns.add(newColumn);
                        newColumn.setActualColumnName(introspectedTable.getTableConfiguration().getTableName());
                        newColumn.setFullyQualifiedJavaType(FullyQualifiedJavaType.getStringInstance());
                        newColumn.setRemarks(introspectedTable.getRemarks());
                        introspectedColumns1.add(newColumn);
                    }
                }
            }
        }

        if (introspectedColumns1.size() > 1) {
            if (properties.containsKey("column_is_first")) {
                List<IntrospectedColumn> introspectedColumns2 = new ArrayList<>();
                if (!CollectionUtils.isEmpty(introspectedColumns1)) {
                    if ("1".equals(properties.getString("column_is_first"))) {
                        introspectedColumns2.add(introspectedColumns1.get(0));
                    } else {
                        for(int i = 1; i < introspectedColumns1.size(); i++) {
                            introspectedColumns2.add(introspectedColumns1.get(i));
                        }
                    }
                }
                introspectedColumns1 = introspectedColumns2;
            } else if(properties.containsKey("column_is_last")) {
                List<IntrospectedColumn> introspectedColumns2 = new ArrayList<>();
                if ("1".equals(properties.getString("column_is_last"))) {
                    introspectedColumns2.add(introspectedColumns1.get(introspectedColumns1.size() - 1));
                } else {
                    for(int i = 0; i < introspectedColumns1.size() - 1; i++) {
                        introspectedColumns2.add(introspectedColumns1.get(i));
                    }
                }
                introspectedColumns1 = introspectedColumns2;
            }
        }
        return introspectedColumns1;
    }

    public DynProcessTokenResult processTokenProperties(IntrospectedTable introspectedTable, SdpTemplateQueryResponse dynTemplate, String fileName, String sqlMethodName, List<IntrospectedColumn> columns, Integer columnIndex, String token, JSONObject properties) throws Exception {
        DynProcessTokenResult result = new DynProcessTokenResult();
        IntrospectedColumn column = null;
        if (columns != null && columnIndex > 0 && columnIndex <= columns.size()) {
            column = columns.get(columnIndex - 1);
        }

        String v = null;
        do {
            if (StringUtility.stringHasValue(properties.getString("has_blobs"))) {
                if ("1".equals(properties.getString("has_blobs"))) {
                    if (!introspectedTable.hasBLOBColumns()) {
                        result.setProcessed(true);
                        continue;
                    }
                } else if ("0".equals(properties.getString("has_blobs"))) {
                    if (introspectedTable.hasBLOBColumns()) {
                        result.setProcessed(true);
                        continue;
                    }
                }
            }
            if (columnIndex != null && properties.containsKey("column_is_last")) {
                if (column == null) {
                    v = "<miss column>:"+token;
                    continue;
                }
                if ("1".equals(properties.getString("column_is_last"))) {
                    if (columnIndex != columns.size()) {
                        result.setProcessed(true);
                        continue;
                    }
                } else if ("0".equals(properties.getString("column_is_last"))) {
                    if (columnIndex == columns.size()) {
                        result.setProcessed(true);
                        continue;
                    }
                }

            }
            if (properties.containsKey("column_is_first")) {
                if (column == null) {
                    v = "<miss column>:"+token;
                    continue;
                }
                if ("1".equals(properties.getString("column_is_first"))) {
                    if (columnIndex != 1) {
                        result.setProcessed(true);
                        continue;
                    }
                } else if ("0".equals(properties.getString("column_is_first"))) {
                    if (columnIndex == 1) {
                        result.setProcessed(true);
                        continue;
                    }
                }
            }

        }while(false);
        result.setResult(v);
        return result;
    }

    public static String md5(String input) {
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            byte[] messageDigest = md.digest(input.getBytes());
            StringBuilder hexString = new StringBuilder();
            for (byte b : messageDigest) {
                String hex = Integer.toHexString(0xff & b);
                if (hex.length() == 1) {
                    hexString.append('0');
                }
                hexString.append(hex);
            }
            return hexString.toString();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public boolean isToken(String tokenIn, String v) {
        tokenIn = tokenIn.trim();
        if (!tokenIn.startsWith("{")) {
            return false;
        }
        tokenIn = SplitUtil.split(tokenIn, "\\{")[1];
        tokenIn = SplitUtil.split(tokenIn, "&")[0];
        tokenIn = SplitUtil.split(tokenIn, "}")[0];

//        return isTokenMD5(tokenIn, v);

        return tokenIn.equals(v);
    }

    public String getName(String token, String name, JSONObject properties, IntrospectedColumn column, IntrospectedTable introspectedTable, SdpTemplateQueryResponse dynTemplate) throws Exception {
        if (properties == null) {
            properties = new JSONObject();
        }
        if (StringUtils.isEmpty(name)) {
            throw new Exception("name is null");
        }
        if ("1".equals(properties.getString("has_java_return_type"))) {
            if (!StringUtils.hasText(column.getParameterJavaReturnType())) {
                return "";
            }
        }
        if ("0".equals(properties.getString("has_java_return_type"))) {
            if (StringUtils.hasText(column.getParameterJavaReturnType())) {
                return "";
            }
        }
        String v;
        if ("1".equals(properties.getString("is_prefix_as_url_ending"))) {
            String[] prefixs = name.split("_");
            if(prefixs.length > 1) {
                String prefixName = prefixs[0].trim();
                if(prefixName.length() > 0) {
                    String prefix_as_package_ending = cn.mysdp.utils.JavaBeansUtil.getJsonString(introspectedTable.getDynProject().getExtraInfo(), "prefix_as_url_leading");
                    if(StringUtils.hasText(prefix_as_package_ending)) {
                        String[] prefix_as_package_endings = prefix_as_package_ending.split(",");
                        for(String p: prefix_as_package_endings) {
                            p = p.trim();
                            String prefix = p;
                            String endings = p;
                            if(p.contains(" as ")) {
                                String [] ps = p.split(" as ");
                                prefix = ps[0].trim();
                                endings = ps[1].trim();
                            }
                            String tName = name;
                            if(tName.startsWith(prefix+"_")) {
                                String _name = name.substring(0, prefix.length());
                                name = endings + "/" + name.substring(_name.length() + 1);
                            }
                        }
                    }
                }
            }
        }

        if ("1".equals(properties.getString("is_prefix_as_rename"))) {
            String[] prefixs = name.split("_");
            if(prefixs.length > 1) {
                String prefixName = prefixs[0].trim();
                if(prefixName.length() > 0) {
                    String prefix_as_package_ending = cn.mysdp.utils.JavaBeansUtil.getJsonString(introspectedTable.getDynProject().getExtraInfo(), "prefix_as_url_leading");
                    if(StringUtils.hasText(prefix_as_package_ending)) {
                        String[] prefix_as_package_endings = prefix_as_package_ending.split(",");
                        for(String p: prefix_as_package_endings) {
                            p = p.trim();
                            String prefix = p;
                            String endings = p;
                            if(p.contains(" as ")) {
                                String [] ps = p.split(" as ");
                                prefix = ps[0].trim();
                                endings = ps[1].trim();
                            }
                            String tName = name;
                            if(tName.startsWith(prefix+"_")) {
                                String _name = name.substring(0, prefix.length());
                                name = endings + "_" + name.substring(_name.length() + 1);
                            }
                        }
                    }
                }
            }
        }

        if("upper_snake".equals(properties.getString("case"))
                || "1".equals(properties.getString("empty_as_upper_snake_alias_table_name"))
                || "1".equals(properties.getString("empty_as_upper_snake_table_name"))
                || "1".equals(properties.getString("empty_as_upper_snake_column_name"))
        ) {
            v = name.toUpperCase();
            if ("1".equals(properties.getString("empty_as_upper_snake_alias_table_name"))) {
                if (StringUtils.hasText(dynTemplate.getAliasTableName())) {
                    v = dynTemplate.getAliasTableName().toLowerCase();
                }
            }
        } else if ("1".equals(properties.getString("is_dash"))) {
            v = name.replaceAll("_", "-");
        } else if ("1".equals(properties.getString("is_ajax"))
                || "lower_snake".equals(properties.getString("case"))
                || "1".equals(properties.getString("empty_as_lower_snake_alias_table_name"))
                || "1".equals(properties.getString("empty_as_lower_snake_table_name"))
                || "1".equals(properties.getString("empty_as_lower_snake_column_name"))
        ) {
            v = name;
            if("1".equals(properties.getString("empty_as_lower_snake_alias_table_name"))) {
                if(StringUtils.hasText(dynTemplate.getAliasTableName())) {
                    v = dynTemplate.getAliasTableName();
                }
            }
        } else if( "1".equals(properties.getString("is_first_lower"))
                || "lower_camel".equals(properties.getString("case"))
                || "1".equals(properties.getString("empty_as_lower_camel_alias_table_name"))
                || "1".equals(properties.getString("empty_as_lower_camel_table_name"))
                || "1".equals(properties.getString("empty_as_lower_camel_column_name"))
        ) {
            v = org.mybatis.generator.internal.util.JavaBeansUtil.getCamelCaseString(name, false);
            if ("1".equals(properties.getString("empty_as_lower_camel_alias_table_name"))) {
                if(StringUtils.hasText(dynTemplate.getAliasTableName())) {
                    v = org.mybatis.generator.internal.util.JavaBeansUtil.getCamelCaseString(dynTemplate.getAliasTableName(), false);
                }
            }
        } else if("1".equals(properties.getString("empty_as_upper_camel_alias_table_name"))) {
            v = org.mybatis.generator.internal.util.JavaBeansUtil.getCamelCaseString(name, true);
            if(StringUtils.hasText(dynTemplate.getAliasTableName())) {
                v = org.mybatis.generator.internal.util.JavaBeansUtil.getCamelCaseString(dynTemplate.getAliasTableName(), true);
            }
        } else if ("1".equals(properties.getString("is_java_name"))) {
            v = org.mybatis.generator.internal.util.JavaBeansUtil.getCamelCaseString(name, false);
        } else {
            v = org.mybatis.generator.internal.util.JavaBeansUtil.getCamelCaseString(name, true);
        }
        if (properties.containsKey("is_rename")) {
            if (!StringUtils.isEmpty(column.getParameterExtraInfo())) {
                try {
                    JSONObject extraInfo = JSON.parseObject(column.getParameterExtraInfo());
                    String name2 = extraInfo.getString(properties.getString("is_rename"));
                    if (StringUtils.hasText(name2)) {
                        v = name2;
                    }
                } catch (Exception ex) {
                    ex.printStackTrace(System.err);
                    throw ex;
                }
            }
        }
        if (properties.containsKey("is_replace_by_sqlparam")) {
            String name2 = "_column:"+column.getActualColumnName()+":"+properties.getString("is_replace_by_sqlparam");
            v = null;
            IntrospectedColumn _replaceCol = cn.mysdp.utils.JavaBeansUtil.getReplaceTableIntrospectedColumn(introspectedTable);
        }
        if ("1".equals(properties.getString("is_like"))) {
            if(introspectedTable.getConfigMap().containsKey("extra_info_sqlparam_is_like")) {
                if(StringUtils.hasText(column.getParameterExtraInfo())) {
                    JSONObject extraInfo = JSON.parseObject(column.getParameterExtraInfo());
                    if(!"1".equals(extraInfo.getString("is_like"))) {
                        v = null;
                    }
                } else {
                    v = null;
                }
            } else {
                if(!(Integer.valueOf(1).equals(column.getParameterIsLike()))) {
                    v = null;
                }
            }
        }
        if (properties.containsKey("is_replace_by_sql")) {
            String name2 = "_column:"+column.getActualColumnName()+":"+properties.getString("is_replace_by_sql");
            v = null;
            IntrospectedColumn _replaceCol = cn.mysdp.utils.JavaBeansUtil.getReplaceTableIntrospectedColumn(introspectedTable);
            if(_replaceCol != null) {
                Map<String, String> replaceTableAnnotationMap = _replaceCol.getReplaceTableAnnotationMap();

                //检查SQL中声明的字段是否存在在表中，以免拼写错误，导致无法排查问题
                if("1".equals(introspectedTable.getConfigMap().get("check_table_field_exist"))) {
                    Set<String> replaceTableAnnotationKeySet = new HashSet<>();
                    replaceTableAnnotationKeySet.addAll(replaceTableAnnotationMap.keySet());
                    for(String _k:replaceTableAnnotationKeySet) {
                        if(_k.startsWith("_column:")) {
                            String _n = _k.split(":")[1];
                            boolean _f = false;
                            for(IntrospectedColumn _c: introspectedTable.getAllColumns()) {
                                if(_n.equals(_c.getActualColumnName())) {
                                    _f = true;
                                    break;
                                }
                            }
                            if (!_f) {
                                if("1".equals(introspectedTable.getConfigMap().get("auto_table_field_exist"))) {
                                    _f = true;
                                    if(StringUtils.hasText(replaceTableAnnotationMap.get("_column:"+_n+":annotation"))) {
                                        if(replaceTableAnnotationMap.get("_column:"+_n+":annotation").replaceAll(" ", "").contains("@TableField(exist=")) {

                                        } else {
                                            replaceTableAnnotationMap.put("_column:"+_n+":annotation", replaceTableAnnotationMap.get("_column:"+_n+":annotation")+System.lineSeparator()+"@TableField(exist = false)");
                                        }
                                    } else {
                                        replaceTableAnnotationMap.put("_column:"+_n+":annotation", "@TableField(exist = false)");
                                    }
                                }
                            }
                            if(!_f && !"1".equals(replaceTableAnnotationMap.get("_column:"+_n+":ignore_check_exist"))) {
                                throw new Exception("SQL中声明的字段不包含在表或结果中：表："+introspectedTable.getFullyQualifiedTable().getIntrospectedTableName()+",字段："+_n+","+_k);
                            }
                        }
                    }
                }

                if(replaceTableAnnotationMap.containsKey(name2)) {
                    v = replaceTableAnnotationMap.get(name2).trim();
                    if ("default_value".equals(properties.getString("is_replace_by_sql"))
                            && StringUtils.hasText(v)
                    ) {
                        v = " = " + v;
                    }
                    if ("default_value".equals(properties.getString("is_replace_by_sqlparam"))
                            && StringUtils.hasText(v)
                    ) {
                        v = " = " + v;
                    }
                    if("1".equals(properties.getString("is_auto_import"))) {

                    }
                }
            }
        }

        if (properties.containsKey("is_replace")) {
            if (!StringUtils.isEmpty(column.getParameterExtraInfo())) {
                try {
                    JSONObject extraInfo = JSON.parseObject(column.getParameterExtraInfo());
                    String name2 = extraInfo.getString(properties.getString("is_replace"));
                    if (StringUtils.hasText(name2)) {
                        v = name2;
                    } else {
                        v = "";
                    }
                } catch (Exception ex) {
                    ex.printStackTrace(System.err);
                    throw ex;
                }
            } else {
                v = "";
            }
        }
        if ("1".equals(properties.getString("is_lower"))) {
            v = v.toLowerCase();
        } else if ("1".equals(properties.getString("is_upper"))) {
            v = v.toUpperCase();
        }

        if ("1".equals(properties.getString("is_java_name"))) {
            if(KeywordUtil.isKeyword(v, "java")) {
                v = "_" + v;
            }
        }
        if ("1".equals(properties.getString("with_delimited")) && column != null
                && column.getContext() != null
                && SqlReservedWords.containsWord(v)) {
            try {
                v = escapeStringForJava(column
                        .getContext().getBeginningDelimiter()) + v + escapeStringForJava(column
                        .getContext().getEndingDelimiter());
            } catch (Exception ex) {
                ex.printStackTrace(System.err);
                throw ex;
            }
        }
        return v;
    }

    public String getCompilationUnits(DataSource dataSource, IntrospectedTable introspectedTable, String template, SdpTemplateQueryResponse dynTemplate, String fileName, String sqlMethodName, Object _processInstance, Method _processBodyToken, Method _processToken) throws Exception {

        byte[] srcBytes = template.getBytes("UTF-8");
        int srcLength = srcBytes.length;

        ByteWithPos destBytes = new ByteWithPos(srcLength*2);

        for(int pos = 0; pos < srcLength; pos++) {
            ByteWithPos lineBytes = new ByteWithPos(1024);

            int srcPos = pos;
            while (pos < srcLength && srcBytes[pos] != '\n') {
                pos++;
            }
            if (srcPos == pos) {
                ByteWithPos.appendLineSeperator(destBytes);
                continue;
            }
            ByteWithPos.appendDestBytes(lineBytes, srcBytes, srcPos, pos);
            String v = new String(lineBytes.bytes, 0, lineBytes.pos, "UTF-8");
            String vTrim = v.trim();
            if ("".equals(vTrim)) {
                ByteWithPos.appendLineSeperator(destBytes);
                continue;
            }
            if (!vTrim.startsWith("{*")) {
                processLine(dataSource, introspectedTable, dynTemplate, fileName, sqlMethodName, lineBytes, destBytes, null, 0, _processInstance, _processBodyToken, _processToken);
                continue;
            }
            pos++;

            List<ByteWithPos> lineBytesList = new ArrayList<>();
            List<String> lineStringList = new ArrayList<>();
            List<String> lineTrimStringList = new ArrayList<>();
            List<Integer> deepList = new ArrayList<>();

            int deep = 1;

            lineBytesList.add(lineBytes);
            deepList.add(deep);
            lineStringList.add(v);
            lineTrimStringList.add(vTrim);

            while (deep > 0 && pos < srcLength) {
                lineBytes = new ByteWithPos(1024);
                srcPos = pos;
                while (pos < srcLength && srcBytes[pos] != '\n') {
                    pos++;
                }
                if (pos == srcLength) {
                    ByteWithPos.appendDestBytes(lineBytes, srcBytes, srcPos, pos);
                    lineBytesList.add(lineBytes);
                    String v2 = new String(srcBytes, srcPos, pos - srcPos, "UTF-8");
                    lineStringList.add(v2);
                    lineTrimStringList.add(v2.trim());
                    deepList.add(deep);
                    break;
                }
                if (srcPos == pos) {
                    ByteWithPos.appendDestBytes(lineBytes, "");
                    lineBytesList.add(lineBytes);
                    lineStringList.add("");
                    lineTrimStringList.add("");
                    deepList.add(deep);
                    pos++;
                    continue;
                }
                ByteWithPos.appendDestBytes(lineBytes, srcBytes, srcPos, pos);
                lineBytesList.add(lineBytes);
                String v2 = new String(lineBytes.bytes, 0, lineBytes.pos, "UTF-8");
                String vTrim2 = v2.trim();
                lineStringList.add(v2);
                lineTrimStringList.add(vTrim2);

                pos++;

                if (vTrim2.equals("{*}")) {
                    deepList.add(deep);
                    deep--;

                    lineBytesList.add(new ByteWithPos(1024));
                    lineStringList.add("{*}");
                    lineTrimStringList.add("{*}");
                    deepList.add(deep);
                } else {
                    if (vTrim2.startsWith("{*")) {
                        deep++;
                    }
                    deepList.add(deep);
                }
            }
            processBodyToken(dataSource, introspectedTable, dynTemplate, fileName, sqlMethodName, lineBytesList, lineStringList, lineTrimStringList, deepList, 1, destBytes, vTrim, null, _processInstance, _processBodyToken, _processToken);
            if (deep == 0) {
                pos--;
            }
        }

        String content = new String(destBytes.bytes, 0, destBytes.pos, "UTF-8");

        return content;

    }

    public DynProcessTokenResult processBodyTokenProperties(DataSource dataSource, IntrospectedTable introspectedTable, SdpTemplateQueryResponse dynTemplate, String fileName, String sqlMethodName, List<ByteWithPos> lineBytesList, List<String> lineStringList, List<String> lineTrimStringList, List<Integer> deepList, int deep, ByteWithPos destBytes, String vTrim, JSONObject properties, List<IntrospectedColumn> inColumns) throws Exception {
        DynProcessTokenResult result = new DynProcessTokenResult();
        if (properties.getString("has_blobs") != null) {
            if ("1".equals(properties.getString("has_blobs")) && !introspectedTable.hasBLOBColumns()) {
                result.setProcessed(true);
                return result;
            }
            if ("0".equals(properties.getString("has_blobs")) && introspectedTable.hasBLOBColumns()) {
                result.setProcessed(true);
                return result;
            }
        }
        if (properties.getString("has_primary_key") != null) {
            if ("1".equals(properties.getString("has_primary_key")) && (introspectedTable.getPrimaryKeyColumns() == null || introspectedTable.getPrimaryKeyColumns().size() == 0)) {
                result.setProcessed(true);
                return result;
            }
            if ("0".equals(properties.getString("has_primary_key")) && introspectedTable.getPrimaryKeyColumns() != null && introspectedTable.getPrimaryKeyColumns().size() > 0) {
                result.setProcessed(true);
                return result;
            }
        }
        if (properties.getString("has_auto_increment") != null) {
            List<IntrospectedColumn> columns = introspectedTable.getAllColumns();
            boolean hasAutoIncrement = false;
            for(IntrospectedColumn column: columns) {
                if (column.isAutoIncrement()) {
                    hasAutoIncrement = true;
                    break;
                }
            }
            if ("1".equals(properties.getString("has_auto_increment")) && !hasAutoIncrement) {
                result.setProcessed(true);
                return result;
            }
            if ("0".equals(properties.getString("has_auto_increment")) && hasAutoIncrement) {
                result.setProcessed(true);
                return result;
            }
        }
        return result;
    }

}
